使用<canvas>元素不是非常難,但需要一些基本的HTML和JavaScript知識。
今天我們來利用canvas API繪制一個時鍾,先上圖:
畫圖之前,先把思路捋一遍:首先分解一下這個時鍾的圖形,它是由表盤(圓形)和指針(直線)組成。
canvas中圓形與矩形差距很大,canvas並沒有提供專門繪制圓形的方法,但可以繪制圓弧,將圓弧首尾相連得到圓形
arc( x , y , radius , 起始弧度 , 結束弧度 , 旋轉方向)
x,y --- 圓心坐標
radius --- 半徑
弧度和角度的關系 --- 弧度 = 角度*Math.PI/180
例:2π是360°(完整的圓形)
旋轉方向 --- true:逆時針;false:順時針(默認)
掌握畫圓大法后,就可以着手施工了:
首先准備好畫布
<canvas id="myClock" width="500" height="500"></canvas>
接着獲取上下文對象
var canvas = document.getElementById('myClock'); var con = canvas.getContext('2d');
分解功能:
1.表盤上的刻度(60個表示秒的刻度,12個表示小時的刻度)
1.1 60個秒刻度-->360°/60-->6°一個小格
//定義原點和半徑 var x = 250; var y = 250; var r = 150; con.moveTo(x,y); con.arc(x,y,r,0,6*Math.PI/180); con.moveTo(x,y); con.arc(x,y,r,6*Math.PI/180,12*Math.PI/180); con.stroke(); ……
先來做個小實驗,以上代碼片段將會得到這個圖形
利用循環,將以上代碼完善
//定義原點和半徑 var x = 250; var y = 250; var r = 150; //繪制秒刻度開始 con.beginPath();//為了不影響其他繪圖,加上起始路徑 for (var i = 0; i < 60; i++) { con.moveTo(x, y); //以圓心為起點 con.arc(x, y, r, 6 * i * Math.PI / 180, 6 * (i + 1) * Math.PI / 180);//繪制一段6°的圓弧 } con.closePath(); //為了不影響其他繪圖,加上起始路徑 con.stroke();
此刻,得到如下圖形
怎么看怎么不像表盤咧?!為了達到秒刻度的效果,只需在上面覆蓋一個較小的白色實心圓形即可
//較小的白色圓盤 con.beginPath(); con.moveTo(x,y); con.arc(x,y,0.95*r,0,2*Math.PI); con.closePath(); con.fillStyle = '#fff';//填充圖形背景色 con.fill(); //實心圓
現在看上去,表盤的雛形算是出來了。
同樣的步驟,將小時刻度也畫出來,為了區分小時刻度和秒刻度,可以加粗小時刻度的線條
1.2 12個小時刻度-->360°/12-->30°一個大格
con.beginPath();//為了不影響其他繪圖,加上起始路徑 con.lineWidth = 4; //加粗小時刻度 for(var i = 0;i<12;i++){ con.moveTo(x,y); con.arc(x,y,r,30*i*Math.PI/180,30*(i+1)*Math.PI/180); } con.closePath(); //為了不影響其他繪圖,加上起始路徑 con.stroke();
最后,再疊加一個較小的白色實心圓心,表盤就畫完了(最難的部分也搞定了)
con.fillStyle = '#fff'; con.beginPath(); con.moveTo(x, y); con.arc(x, y, 0.85 * r, 0, 2 * Math.PI); con.closePath(); con.fill();
總得來說,畫表盤就和化妝一樣,需要層層疊加
2.時、分、秒針
//注意:考慮到針要以圓心為中心旋轉 con.lineWidth = 5; //定義時針線條的寬度 con.beginPath(); con.moveTo(x,y); //還是以圓心為起點 con.arc(x,y,0.5*r,0,0);//此處半徑即時針的長度 con.closePath(); con.stroke();
分針和秒針就不做贅述,修改lineWidth的值和圓弧的半徑即可
3.讓時鍾走起來
如何讓秒針隔一秒動一下呢?是不是很快想到這個方法--->setInterval()
…… //獲取當前系統時間 var today = new Date(); var hh = today.getHours(); var mm = today.getMinutes(); var ss = today.getSeconds(); //時針對應的弧度 var hhVal = (-90 + hh * 30 + mm / 2)*Math.PI/180; //-90:canvas畫圓的起始點在表盤的3個字,而時鍾的起始點應在12個字。+mm/2:時針不會一直只在整點的位置,分針走30分鍾,時針多走15° var mmVal = (-90 + mm * 6) * Math.PI / 180; var ssVal = (-90 + ss * 6) * Math.PI / 180; …… con.arc(x, y, 0.5 * r, hhVal, hhVal); …… //調用函數 setInterval(toDraw, 1000);
組合好代碼后,時鍾就能走起來了:(^-^)V
奉上完整代碼:
HTML部分
<canvas id="myClock" width="500" height="500"></canvas> <p id="showDate"></p>
JavaScript部分
window.onload = function () { //獲取上下文對象 var canvas = document.getElementById('myClock'); var con = canvas.getContext('2d'); //自定義函數---畫表盤,針 function toDraw() { //定義原點和半徑 var x = 250; var y = 250; var r = 150; //繪制秒刻度開始 con.beginPath(); for (var i = 0; i < 60; i++) { con.moveTo(x, y);//以圓心為起點 con.arc(x, y, r, 6 * i * Math.PI / 180, 6 * (i + 1) * Math.PI / 180);//繪制一段6°的圓弧 } con.closePath(); //為了不影響其他繪圖,加上起始路徑 con.stroke(); //較小的白色圓盤 con.fillStyle = '#fff'; con.beginPath(); con.moveTo(x, y); con.arc(x, y, 0.95 * r, 0, 2 * Math.PI); con.closePath(); con.fill(); //實心圓 //繪制秒刻度結束 //同理繪制小時刻度 con.beginPath(); con.lineWidth = 4; //加粗小時刻度 for (var i = 0; i < 12; i++) { con.moveTo(x, y); con.arc(x, y, r, 30 * i * Math.PI / 180, 30 * (i + 1) * Math.PI / 180); } con.closePath(); //為了不影響其他繪圖,加上起始路徑 con.stroke(); //較小的白色圓盤 con.fillStyle = '#fff'; con.beginPath(); con.moveTo(x, y); con.arc(x, y, 0.85 * r, 0, 2 * Math.PI); con.closePath(); con.fill(); //繪制小時刻度結束 //獲取當前系統時間 var today = new Date(); var hh = today.getHours(); var mm = today.getMinutes(); var ss = today.getSeconds(); document.getElementById('showDate').innerHTML = hh+':'+mm+':'+ss; //時針對應的弧度 var hhVal = (-90 + hh * 30 + mm / 2) * Math.PI / 180; var mmVal = (-90 + mm * 6) * Math.PI / 180; var ssVal = (-90 + ss * 6) * Math.PI / 180; //開始繪制時、分、秒針(注意:考慮到針要以原點為中心旋轉) con.lineWidth = 5; //時針 con.beginPath(); con.moveTo(x, y); con.arc(x, y, 0.5 * r, hhVal, hhVal); con.closePath(); con.stroke(); con.lineWidth = 3; //分針 con.beginPath(); con.moveTo(x, y); con.arc(x, y, 0.65 * r, mmVal, mmVal); con.closePath(); con.stroke(); con.lineWidth = 1; //秒針 con.beginPath(); con.moveTo(x, y); con.arc(x, y, 0.8 * r, ssVal, ssVal); con.closePath(); con.stroke(); } //每隔1秒調用一次函數 setInterval(toDraw, 1000); }