深入理解Canvas模糊問題產(chǎn)生的原因與解決辦法
我們?cè)谑褂肅anvas進(jìn)行繪圖時(shí),經(jīng)常會(huì)出現(xiàn)繪制的文字或者圖片比較模糊,下面讓我們看一下其產(chǎn)生的原因以及如何解決這個(gè)問題。
一、模糊產(chǎn)生的原因
1、style 和 canvas 中定義的寬高不一致造成的
通常,在定義 canvas 時(shí)我們會(huì)這么寫:
<canvas width="300" height="150" style="width: 300px; height: 150px;" id="canvas"></canvas>
其中,width、height 為 canvas 中繪制的大小,canvas 可以看成是一個(gè)畫布,而 width、height 則分別代表這個(gè)畫布所繪制區(qū)域的寬高。而 style 中定義的 width、height 則代表實(shí)際渲染到頁(yè)面上的寬高。
那么問題來(lái)了,當(dāng) width、height 和 style 中定義的 width、height 不一致時(shí),canvas 中繪制的元素會(huì)根據(jù) width、height 進(jìn)行縮放或者拉伸到 style 中所定義的 width、height,這就會(huì)導(dǎo)致所繪制的圖像比較模糊。
2、所繪制的像素不足 1px
在屏幕上繪制圖像時(shí),最少支持的也是繪制 1px,那么比如我們繪制 0.5px,canvas 會(huì)將使用填充算法將其擴(kuò)展到 1px,如果所擴(kuò)展的顏色跟原來(lái)的顏色一致,那么肯定沒有問題,但是會(huì)產(chǎn)生鋸齒狀的一個(gè)效果,所以 canvas 會(huì)采取周圍的顏色取一個(gè)平均值,這就會(huì)導(dǎo)致模糊的產(chǎn)生。所以盡量不要設(shè)置半個(gè)像素。
3、受到高清屏幕的影響
在我們的普通屏幕上,設(shè)備像素比(Device Pixel Ratio:屏幕的物理像素 / css像素)為 1:1,在這種情況下不會(huì)產(chǎn)生模糊的問題。但是如果我們?cè)谝粋€(gè) 4k 的屏幕上,設(shè)備像素比為 1.5,那么也就是說(shuō)屏幕的物理像素 / css像素等于 1.5,即一個(gè) css 像素會(huì)渲染到 1.5 個(gè)設(shè)備像素上,這就會(huì)導(dǎo)致 css 像素會(huì)進(jìn)行擴(kuò)展,從而產(chǎn)生模糊的問題。
既然知道產(chǎn)生的原因,那么解決起來(lái)就很簡(jiǎn)單了。其主要的思想就是對(duì) canvas 的 width、height 進(jìn)行擴(kuò)展,也就是擴(kuò)展 canvas 畫布的大小,但是 style 中的 width、height 并沒有改變,這樣 canvas 會(huì)進(jìn)行縮放,這樣一來(lái),點(diǎn)就變多了,但是 canvas 本身的大小并沒有改變(同二倍圖、多倍圖的原理相似)。
二、解決方法
具體來(lái)說(shuō),有兩種解決方法:
方法一
擴(kuò)展 canvas 并對(duì) canvas 的繪制上下文也進(jìn)行擴(kuò)展,相當(dāng)于同時(shí)擴(kuò)展畫布和畫筆。
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const dpr = window.devicePixelRatio;
const { width, height } = canvas;
canvas.width = Math.round(width * dpr);
canvas.height = Math.round(height * dpr);
ctx.font = "bold 40px 宋體";
ctx.scale(dpr, dpr);
ctx.fillText("你好呀", canvas.clientWidth / 2, canvas.clientHeight / 2);
方法二
擴(kuò)展 canvas,不擴(kuò)展 canvas 繪制上下文,但在每次繪制元素時(shí),需要對(duì)所繪制的元素進(jìn)行擴(kuò)展(即乘以一個(gè)設(shè)備像素比)。
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const dpr = window.devicePixelRatio;
const { width, height } = canvas;
canvas.width = Math.round(width * dpr);
canvas.height = Math.round(height * dpr);
// ctx.scale(dpr, dpr);
ctx.font = "bold 40px 宋體";
ctx.fillText("你好呀", (canvas.clientWidth / 2) * dpr, (canvas.clientHeight / 2) * dpr);
三、知識(shí)補(bǔ)充
除了上文的方法,小編還為大家整理了其他Canvas模糊問題產(chǎn)生的解決方法,希望對(duì)大家有所幫助
方法
第一步:獲取像素比
第二步:將 canvas 標(biāo)簽上的寬高屬性設(shè)置為 顯示大小 * 像素比
第三步:將 canvas 樣式寬高設(shè)置為 顯示大小
第四步:使用 scale 方法設(shè)置比值
第五步:繪制 canvas 圖形
function createHDCanvas (canvas, w, h) {
const ratio = window.devicePixelRatio || 1;
canvas.width = w * ratio; // 實(shí)際渲染像素
canvas.height = h * ratio; // 實(shí)際渲染像素
canvas.style.width = `${w}px`; // 控制顯示大小
canvas.style.height = `${h}px`; // 控制顯示大小
const ctx = canvas.getContext('2d')
ctx.scale(ratio, ratio)
// canvas 繪制
return canvas;
}
到此這篇關(guān)于深入理解Canvas模糊問題產(chǎn)生的原因與解決辦法的文章就介紹到這了,更多相關(guān)Canvas模糊問題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js判斷主流瀏覽器類型和版本號(hào)的簡(jiǎn)單實(shí)現(xiàn)代碼
下面小編就為大家?guī)?lái)一篇js判斷主流瀏覽器類型和版本號(hào)的簡(jiǎn)單實(shí)現(xiàn)代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2016-05-05
iframe實(shí)現(xiàn)與父頁(yè)面跨域隔離的JavaScript?代碼沙箱
這篇文章主要介紹了使用iframe實(shí)現(xiàn)與父頁(yè)面跨域隔離的JavaScript代碼沙箱,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
微信小程序wxml不能使用Array.includes條件判斷解決方法
這篇文章主要為大家介紹了微信小程序wxml不能使用Array.includes條件判斷解決方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
打字效果動(dòng)畫的4種實(shí)現(xiàn)方法(超簡(jiǎn)單)
下面小編就為大家?guī)?lái)一篇打字效果動(dòng)畫的4種實(shí)現(xiàn)方法(超簡(jiǎn)單)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-10-10
TypeScript內(nèi)置工具類型快速入門運(yùn)用
TypeScript 中內(nèi)置了很多工具類型,我們無(wú)需導(dǎo)入,可以直接使用。 其中的很多都是比較常用的,接下來(lái)我們根據(jù)使用范圍來(lái)一一介紹,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-03-03
11個(gè)教程中不常被提及的JavaScript小技巧(推薦)
這篇文章主要介紹了11個(gè)教程中不常被提及的JavaScript小技巧,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
javascript中延遲加載的7種方法實(shí)現(xiàn)
在web前端開發(fā)中,性能優(yōu)化一直是一個(gè)非常重要的話題,JavaScript中延遲加載的方式有很多種,本文就來(lái)介紹了javascript中延遲加載的7種方法實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-01-01
JavaScript簡(jiǎn)單實(shí)現(xiàn)彈出拖拽窗口(二)
這篇文章再次為大家詳細(xì)介紹了JavaScript簡(jiǎn)單實(shí)現(xiàn)彈出拖拽窗口的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06

