實踐demo——「canvas離屏、旋轉效果實踐——旋轉的雪花」html
前幾天研究html2Canvas的時候恰好遇上做者發佈新版本,發現新版本截屏出來的效果比我對舊版本處理後(畫布尺寸都設爲2倍)的效果更好。 扒源碼的時候發現他們並無直接設爲兩倍尺寸,而是先獲取當前dom結構的scale,用當前dom的scale去設置canvas的畫布尺寸比。 我本身手機上測試時打印出來的dom的scale顯示爲3倍尺寸,因此我設置canvas兩倍畫布尺寸的時候,其實仍是會模糊的,不過對比1倍尺寸的是要清晰不少了。
問題緣由canvas
查閱canvas的API就能夠知道,想要得到精確地線條,必須對線條是如何描繪出來的有所理解。segmentfault
首先要清楚一點:canvas畫線時的定位定的是線條中線的位置,根據線條的寬度再向兩邊延伸,若是延伸出去的線條沒有佔滿1px,不足的部分將會以實際筆觸顏色的一半色調來填充。因此最後咱們實際看到的效果就是:1px的線條變寬了,且變模糊了,效果如左圖所示:緩存
解決辦法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圖片:字體
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中有兩個很好用的東西:旋轉和保存狀態。
以畫圓的不一樣角度的半徑爲例,正常狀況下咱們要根據圓半徑、線的角度和圓心的位置計算得出線的端點座標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}的線。
另一定要注意:
修改畫布座標系(定原點、旋轉畫布)以前必定要保存狀態,畫完線後必定要重載狀態!否則你會很容易被本身改過的座標系玩死的。