上一篇文章我們使用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);

};
</script>
</head>
<body>
<canvas width="800" height="500">
<span>你的瀏覽器不支持canvas</span>
</canvas>
</body>
</html>

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繪製數據扇形圖。


推薦閱讀:
相关文章