上一篇文章我們使用Canvas繪製了動態屏保,重點講了一下arc函數和requestAnimationFrame的應用。
這節課呢我們在加深一下arc和requestAnimationFrame,實現一個WiFi信號。效果圖,如下:
看到這個圖,我們分析一下思路,我們分三步:
第一步,我們先畫一個弧形;
第二步,我們畫一組弧形;
第三,我們讓一組弧形動起來。
我們一步步來,首先,我們先整一個html頁面:
? <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width_=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <title>document</title> <style> *{ padding:0; margin:0; } html,body{ width:100%; height:100%; overflow: hidden; background: #000; } canvas{ background:#fff; } span{ font-size: 50px; } </style> <script> ? </script> </head> <body> <canvas width="800" height="500"> <span>你的瀏覽器不支持canvas</span> </canvas> </body> </html>
ok,我們搭好了架子,開始準備做基礎工作,我們先複習一下上一篇文章寫的arc函數,搞一個弧形出來,如圖所示
只要有一個弧形出來了,其它就好辦了,這個我們輕車熟路,走起。
? <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width_=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <title>document</title> <style> *{ padding:0; margin:0; } html,body{ width:100%; height:100%; overflow: hidden; background: #000; } canvas{ background:#fff; } span{ font-size: 50px; } </style> <script> window.onload=function(){ var c=document.getElementsByTagName(canvas)[0]; //準備畫筆 var gd=c.getContext(2d); gd.lineWidth=20; gd.strokeStyle=red; gd.arc(200,200,100,-Math.PI/2,0,false); ? gd.stroke(); }; </script> </head> <body> <canvas width="800" height="500"> <span>你的瀏覽器不支持canvas</span> </canvas> </body> </html>
刷新頁面,一個優雅的弧形就出來了(好吧,我也不知道它優雅在哪),因為arc函數是老相識了,這裡我就不墨跡。
var c=document.getElementsByTagName(canvas)[0]; //準備畫筆 var gd=c.getContext(2d); gd.lineWidth=20; gd.strokeStyle=red; gd.arc(200,200,100,-Math.PI/2,0,false); ? gd.stroke();
接下來,我們完全可以算好間距,和位置,重複代碼寫三次,這事兒就完成了。但是,大量重複的代碼顯然不符合程序規範,也不好管理,後續我們做動畫的時候,更不好處理,所以我們封裝一個函數,專門畫弧的。
function drawArc(start,end,r){ gd.arc(200,200,r,d2a(start),d2a(end),false); gd.stroke(); }
這個函數還是極其簡單的,因為WiFi信號其實就是同心圓的一部分,所以我們不用確定圓心,只要確定起始角度start,終止角度end,以及半徑r就ok了,當然了,我們還需要一個輔助函數,角度轉弧度,
function d2a(n){ n-=90; return n*Math.PI/180; }
怎麼推出來的也很簡單,180度等於π弧度。然後一轉換就OK了。
我們拿封裝好的函數,試一下,
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width_=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <title>document</title> <style> *{ padding:0; margin:0; } html,body{ width:100%; height:100%; overflow: hidden; background: #000; } canvas{ background:#fff; } span{ font-size: 50px; } </style> <script> function d2a(n){ n-=90; return n*Math.PI/180; } window.onload=function(){ var c=document.getElementsByTagName(canvas)[0]; //準備畫筆 var gd=c.getContext(2d); gd.lineWidth=15; gd.strokeStyle=red; function drawArc(start,end,r){ gd.arc(200,200,r,d2a(start),d2a(end),false); gd.stroke(); } ? drawArc(-45,45,30); drawArc(-45,45,60); drawArc(-45,45,90);
}; </script> </head> <body> <canvas width="800" height="500"> <span>你的瀏覽器不支持canvas</span> </canvas> </body> </html>
出事兒了,我仔細看一下,其實畫的是對的,但是問題出在,同時畫的時候沒有把筆抬起來,也就是沒有beginPath,這個是很常見的一個錯誤。
怎麼修復呢?
代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width_=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <title>document</title> <style> *{ padding:0; margin:0; } html,body{ width:100%; height:100%; overflow: hidden; background: #000; } canvas{ background:#fff; } span{ font-size: 50px; } </style> <script> function d2a(n){ n-=90; return n*Math.PI/180; } window.onload=function(){ var c=document.getElementsByTagName(canvas)[0]; //準備畫筆 var gd=c.getContext(2d); gd.lineWidth=15; gd.strokeStyle=red; function drawArc(start,end,r){ gd.beginPath(); gd.arc(200,200,r,d2a(start),d2a(end),false); gd.stroke(); } ? drawArc(-45,45,30); drawArc(-45,45,60); drawArc(-45,45,90);
so easy,媽媽再也不用擔心我的連筆問題了。ok,解決了連筆問題,我們開始加動畫。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width_=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <title>document</title> <style> *{ padding:0; margin:0; } html,body{ width:100%; height:100%; overflow: hidden; background: #000; } canvas{ background:#fff; } span{ font-size: 50px; } </style> <script> function d2a(n){ n-=90; return n*Math.PI/180; } window.onload=function(){ var c=document.getElementsByTagName(canvas)[0]; //準備畫筆 var gd=c.getContext(2d); gd.lineWidth=15; gd.strokeStyle=red; function drawArc(start,end,r){ gd.beginPath(); gd.arc(200,200,r,d2a(start),d2a(end),false); gd.stroke(); } ? var r=0; setInterval(function(){ r+=30;
drawArc(-45,45,r); ? if(r>100){ r=0; gd.clearRect(0,0,c.width,c.height); } },300) }; </script> </head> <body> <canvas width="800" height="500"> <span>你的瀏覽器不支持canvas</span> </canvas> </body> </html>
效果如下:
效果還是很OK的,好我們看一下注意的問題:
setInterval(function(){ r+=30;
drawArc(-45,45,r); ? if(r>100){ r=0; gd.clearRect(0,0,c.width,c.height); } },300)
為什麼用它原因很簡單,因為我們上一篇文章用了處理requestAnimationFrame。
//採用IIFE,處理requestAnimationFrame兼容性 window.requestAnimationFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60);//低版本保險刷新頻率 }; })();
所以這篇文章我們變著法的玩,讓大家多接觸一些不同的實現方式,
第二個問題:
if(r>100){ r=0; gd.clearRect(0,0,c.width,c.height); }
清空時機的控制。
用canvas畫WiFi還是用途很廣泛的,比如用canvas做背景,還有經常打架會看到一些動畫網站飄來飄去的雲,都是這個原理。
1.首先我們分析了畫WiFi的步驟,正確的拆解問題是我們解決問題的基礎。
2.我們複習了Arc函數
3.我們封裝了drawArc函數,在實際工作中大家也要注意,重複的代碼一定要封裝
4.注意beginPath的使用
5.定時器的使用,有時候requestAnimationFrame兼容性不好的時候,setInterval是你最後的選擇
6.最後我們注意清空的時機
好,這篇文章我們就到這裡,下一篇文章我們要講一個在工作中更加常用的情景 -使用canvas繪製數據扇形圖。