canvas總結:線段寬度與像素邊界


canvas中,我們經常需要繪制線段,主要使用moveTolineTo兩個方法,moveTo移動至線段起始點,lineTo將線段繪制至終點。同時,繪制線段時可以指定線段的寬度,使用lineWidth屬性,lineWidth默認為1,必須大於0

moveTo(x, y): 移動至坐標xy

lineTo(x, y): 線段終點坐標xy

簡單繪制代碼如下:

var context = document.getElementById('canvas').getContext('2d');
context.lineWidth = 2; //設置線寬
context.beginPath(); //開始繪制路徑
context.moveTo(0, 50); //移動至起始點
context.lineTo(50, 50); //移動至終點
context.stroke(); //繪制

Done, 繪制出了一條線寬為2的線段,就這么簡單

那我們再繪制一條線寬為1的線段

context.lineWidth = 1;
context.beginPath();
context.moveTo(50, 50);
context.lineTo(100, 50);
context.stroke();

我勒個去,怎么跟線寬2的寬度是一樣的,寬度也是2,只是顏色稍淺。

那我們換個思路,剛才繪制的Y軸左邊為50,我們改成50.5呢,分別再繪制兩條線寬分別是21的線段

context.lineWidth = 2;
context.beginPath();
context.moveTo(0, 70.5);
context.lineTo(50, 70.5);
context.stroke();

context.lineWidth = 1;
context.beginPath();
context.moveTo(0, 80.5);
context.lineTo(50, 80.5);
context.stroke();

從上至下分別稱為線段1234

顯然,線段312都要寬,實際為3px,線段4實際為1px

線段1:繪制線寬2, 實際寬度2

線段2:繪制寬度1, 實際寬度2

線段3:繪制寬度2, 實際寬度3

線段4:繪制寬度1: 實際寬度1

只有14才是我們想要的結果

為什么呢?

其實,這跟canvas的繪制邏輯有關,當我們試圖繪制一個線段時,canvas會讀取lineWidth,,然后嘗試將在坐標處兩邊各繪制一半的lineWidth,比如我們下圖:

 

我們在坐標3處畫一條寬為1的橫線,canvas會以3為中軸線,在兩邊各畫0.5像素,深藍色就是我們期望的效果(2.5-3.51個像素),但實際上,淺藍色也會被繪制出來,因為canvas無法在整個像素寬內只繪制半個像素,所以坐標軸上下兩個方向都都會被擴展至整個像素寬度內(2-4,兩個像素),但是擴展的像素實際的值並不是原值相同,而是取其一半,所以最直接的視覺感受是:線條比預想的變寬了,但是顏色淺了很多。

 

還是以寬為1的橫線為例,我們如果將其繪制在縱坐標2.5處呢,即以半像素作為中軸線

 

同樣瀏覽器進行繪制時,在2.5上下各繪制0.5的像素寬度,但與上面的例子不同的是,圖像邊界正好落在整數像素邊界內,合起來正好為1個像素,這個時候,就不需要向兩邊擴展,而是我們預期的(2-3)的1個像素寬度。

同理,我們分別使用兩種方式繪制寬度為2的線段時,效果恰恰相反,在坐標3處繪制的時候,像素正好擴展至2-4,即2個像素,符合我們的預期;而在坐標2.5處繪制時,像素擴展至1.5-3.5,未到邊界,需要補足,就變成了1-4,即3個像素。

建議

在實際應用中,如果想得到更好的體驗,精確的像素值,如果線段的寬度是奇數像素,繪制時以n.5,即半數像素作為中軸線,如果線段的寬度為偶數像素,繪制時以n.0,即整數像素作為中軸線


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM