常見的canvas優化——模糊問題、旋轉效果

canvas常見優化方案——模糊問題、旋轉效果、離屏、自定義圖片尺寸

實踐demo——「canvas離屏、旋轉效果實踐——旋轉的雪花」html

2017-12-18 16:27:35更新關於模糊問題

前幾天研究html2Canvas的時候恰好遇上做者發佈新版本,發現新版本截屏出來的效果比我對舊版本處理後(畫布尺寸都設爲2倍)的效果更好。
扒源碼的時候發現他們並無直接設爲兩倍尺寸,而是先獲取當前dom結構的scale,用當前dom的scale去設置canvas的畫布尺寸比。
我本身手機上測試時打印出來的dom的scale顯示爲3倍尺寸,因此我設置canvas兩倍畫布尺寸的時候,其實仍是會模糊的,不過對比1倍尺寸的是要清晰不少了。

canvas顯示模糊問題——畫布尺寸設爲顯示尺寸的兩倍便可

問題緣由canvas

查閱canvas的API就能夠知道,想要得到精確地線條,必須對線條是如何描繪出來的有所理解。segmentfault

首先要清楚一點:canvas畫線時的定位定的是線條中線的位置,根據線條的寬度再向兩邊延伸,若是延伸出去的線條沒有佔滿1px,不足的部分將會以實際筆觸顏色的一半色調來填充。因此最後咱們實際看到的效果就是:1px的線條變寬了,且變模糊了,效果如左圖所示:緩存

clipboard.png

解決辦法dom

根據問題緣由咱們知道:只要從線條中線開始向外延伸部分佔滿1px,就不會出現線條變寬且模糊的問題了。函數

最簡單的辦法是畫線時根據需求將線條定位移動0.5px,不過這是治標不治本的方法,只能用來驗證這個方法是否是正確的。佈局

咱們還能夠將畫布尺寸設爲顯示尺寸的2倍,這至關於用畫圖時的兩個像素點去填充實際顯示的一個像素點,這樣就能很好的解決canvas顯示模糊的問題了。性能

canvas.setAttribute('width', x * 2);
canvas.setAttribute('height', y * 2);
canvas.style.width = x + 'px';
canvas.style.height = y + 'px';

用這種方法要記得:各類佈局尺寸也要作相應變化。測試

離屏canvas

定義離屏canvas,在離屏canvas上設定畫布尺寸並繪製canvas圖片:字體

var offScreenCanvas = document.createElement('offScreenCanvas');
var offScreenCtx = offScreenCanvas.getContext('2d');

而後將畫好的離屏canvas繪製到實際顯示的canvas上:

ctx.drawImage(offScreenCanvas, 0, 0, offScreenCanvas.width, offScreenCanvas.height,
    0, 0, canvas.width, canvas.height);

好處

一是能夠不受限於html標籤及實際顯示尺寸,畫出一個標準尺寸的大圖,而後自適應到實際顯示的canvas上;
二是離屏canvas的緩存效果能夠大大提高canvas的性能(固然像上述那樣粗糙的代碼,是體現不出這一效果的)。

不足

離屏canvas必定要畫好以後才能繪製到實際顯示的canvas上,這就致使哪些有延時的元素不方便這樣用(如圖片、自定義字體等)。針對這一問題,目前我尚未找到好的解決辦法。

圖片尺寸問題

剛開始畫圖的時候很糾結的一個問題就是:canvas畫png圖片時,不一樣屏幕尺寸要配多大的圖、配幾套。後來在解決上述「離屏canvas」的問題後,這個問題也就迎刃而解了:drawImage函數能夠設定將圖片繪製成多大的,而不限定於圖片自己的尺寸。

這個問題解決以後,就只須要一套圖片就行了,還可使圖片大小自適應屏幕、隨顯示界面縮放。

canvas旋轉效果——改變了畫布座標系

canvas中有兩個很好用的東西:旋轉和保存狀態。

以畫圓的不一樣角度的半徑爲例,正常狀況下咱們要根據圓半徑、線的角度和圓心的位置計算得出線的端點座標P1{x1,y1}、P2{x2,y2},而後畫一條P1到P2的線,代碼中的計算量不小。不過canvas中咱們有更好的解決辦法:

1.定位筆觸到圓心位置{x,y}

ctx.translate(x,y)

2.根據線的角度旋轉畫布angle圈(angle=1時表示順時針旋轉一圈)

ctx.rotate(Math.PI*2 * angle);

3.畫一條{0,0}到{r,0}的線便可

ctx.beginPath();
ctx.lineTo(0, 0);
ctx.lineTo(r, 0);
ctx.stroke();

canvas旋轉方式畫線步驟解讀:

筆觸定位至關因而定畫布原點的位置,旋轉畫布則是以原點爲圓心順時針旋轉了x/y座標系,旋轉後的效果是將x正半軸與要畫的線重合,天然就至關於直接畫一條{0,0}到{r,0}的線。

另一定要注意

修改畫布座標系(定原點、旋轉畫布)以前必定要保存狀態,畫完線後必定要重載狀態!否則你會很容易被本身改過的座標系玩死的。

相關文章
相關標籤/搜索