JS在Canvas元素內(nèi)繪制鐘表
首先,canvas語(yǔ)法基礎(chǔ)薄弱的小伙伴請(qǐng)點(diǎn)這里,剩下的小伙伴們可以接著往下看了。
一個(gè)表,需要畫什么出來(lái)呢:3條線(時(shí)分秒針),1個(gè)圓(表盤),以及60條短線/點(diǎn)(刻度)。
嗯,沒(méi)毛病。
那接下來(lái)讓我們考慮點(diǎn)細(xì)節(jié):一個(gè)圓,自然是360°,分成60個(gè)刻度,兩個(gè)刻度之間相隔6°,然后分針和秒針刻度偏移是相同的,時(shí)針的刻度偏移應(yīng)該是它們的5倍(只有12個(gè)小時(shí)刻度)=30°,然而你見(jiàn)過(guò)時(shí)分秒針一樣長(zhǎng)的表么?(我反正沒(méi)有)所以我們還需要控制它們的長(zhǎng)度是不一樣的才對(duì)。
咳,有了上面的思考作為基礎(chǔ)了,開搞。
先定個(gè)點(diǎn)畫個(gè)圓:
var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.arc(X坐標(biāo), Y坐標(biāo), 半徑, 0, 2 * Math.PI, false); ctx.strokeStyle = 隨便填顏色; ctx.stroke(); ctx.closePath();
接下來(lái)我們要打上時(shí)間刻度,可是問(wèn)題來(lái)了:你是可以畫出來(lái)一個(gè)圓,也知道每個(gè)刻度6°角,可如何在畫出來(lái)的圓上找到對(duì)應(yīng)的坐標(biāo)呢?
don't worry(數(shù)學(xué)知識(shí)過(guò)關(guān)的小伙伴們表示毫無(wú)壓力)~我們只需要去算出正余弦就拿到了對(duì)應(yīng)的XY坐標(biāo)啦(是的,腳本內(nèi)正余弦算法不是算角度),具體做法如下:
//計(jì)算圓上每個(gè)點(diǎn)的坐標(biāo) ///[a]角度[i]刻度[ox]圓心X坐標(biāo)[oy]圓心Y坐標(biāo)[or]圓半徑 function angle(a, i, ox, oy, or) { var hudu = (2 * Math.PI / 360) * a * i;//求出弧度 var x = ox + Math.sin(hudu) * or;//計(jì)算出x軸坐標(biāo)for正弦 var y = oy - Math.cos(hudu) * or;//計(jì)算出y軸坐標(biāo)for余弦 return x + '_' + y; }
到了這里,我們就可以愉快的畫刻度了:
//打上文字(僅小時(shí)) for (var i = 0; i < 12; i++) { var textXY = angle(30, i + 1, ox, oy, or - 10);//小時(shí)刻度坐標(biāo) ctx.fillText(i + 1, textXY.split('_')[0], textXY.split('_')[1]); ctx.textAlign = 'center';//水平居中 ctx.textBaseline = 'middle';//垂直居中 } //打上分秒鐘刻度 for (var i = 0; i < 60; i++) { var oXY = angle(6, i + 1, ox, oy, or);//分、秒刻度坐標(biāo) ctx.beginPath(); ctx.arc(oXY.split('_')[0], oXY.split('_')[1], (i + 1) % 5 == 0 ? 2 : 1, 0, 2 * Math.PI); ctx.fillStyle = 'blue'; ctx.fill(); ctx.closePath(); }
為了逼真,我還加入了秒針影響分針,分針影響秒針的計(jì)算。(見(jiàn)最后代碼)
然后就是考慮三根針不一樣長(zhǎng)的問(wèn)題,這個(gè)問(wèn)題試過(guò)很多遍,最后我發(fā)現(xiàn)最簡(jiǎn)單的解決辦法就是多畫3個(gè)圓,因?yàn)槠频慕嵌扔?jì)算方式是一樣的。
最后的結(jié)果是這樣的:
因?yàn)椴恢С稚蟼鱤tml文件,所以我就把所有代碼貼在這里了:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>小馬的canvas練手作品-時(shí)鐘</title> <meta charset="utf-8" /> </head> <body> <canvas id="myCanvas" width="1000" height="1000">您的瀏覽器不支持此標(biāo)簽</canvas> <script type="text/javascript"> setInterval('drawClock(150, 150, 100, 50, 70, 90,"pink","black","red","green")', 1000); //畫鐘表 //[ox]圓心X坐標(biāo)[oy]圓心Y坐標(biāo)[or]鐘表半徑[hr]時(shí)針半徑[mr]分針半徑[sr]秒針半徑[oc]鐘表外環(huán)顏色[hc]時(shí)針顏色[mc]分針顏色[sc]秒針顏色 function drawClock(ox, oy, or, hr, mr, sr, oc, hc, mc, sc) { //時(shí)鐘底盤 var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.clearRect(ox - or, oy - or, or * 2, or * 2);//清空上一次繪制 ctx.beginPath(); ctx.arc(ox, oy, or, 0, 2 * Math.PI, false); ctx.strokeStyle = oc; ctx.stroke(); ctx.closePath(); //獲取當(dāng)前時(shí)間 var NowTime = new Date(); var h = NowTime.getHours(); var m = NowTime.getMinutes(); var s = NowTime.getSeconds(); var y = NowTime.getFullYear(); var mo = NowTime.getMonth() + 1; var d = NowTime.getDate(); ctx.fillText(mo + '月' + d + '日', ox, oy - or / 2, 50);//顯示月日 //打上時(shí)間刻度 for (var i = 0; i < 12; i++) { var textXY = angle(30, i + 1, ox, oy, or - 10);//小時(shí)刻度坐標(biāo) ctx.fillText(i + 1, textXY.split('_')[0], textXY.split('_')[1]); ctx.textAlign = 'center';//水平居中 ctx.textBaseline = 'middle';//垂直居中 } //打上分鐘刻度 for (var i = 0; i < 60; i++) { var oXY = angle(6, i + 1, ox, oy, or);//分、秒刻度坐標(biāo) ctx.beginPath(); ctx.arc(oXY.split('_')[0], oXY.split('_')[1], (i + 1) % 5 == 0 ? 2 : 1, 0, 2 * Math.PI); ctx.fillStyle = 'blue'; ctx.fill(); ctx.closePath(); } h = h + m / 60;//分鐘影響時(shí)針偏移 var hoursXY = angle(30, h > 12 ? h - 12 : h, ox, oy, hr);//時(shí)針終點(diǎn)XY坐標(biāo) drawLine(ctx, hc, ox, oy, hoursXY.split('_')[0], hoursXY.split('_')[1]); m = m + s / 60;//秒鐘影響分針偏移 var minuteXY = angle(6, m, ox, oy, mr);//分針終點(diǎn)XY坐標(biāo) drawLine(ctx, mc, ox, oy, minuteXY.split('_')[0], minuteXY.split('_')[1]); var secondXY = angle(6, s, ox, oy, sr);//秒針終點(diǎn)XY坐標(biāo) drawLine(ctx, sc, ox, oy, secondXY.split('_')[0], secondXY.split('_')[1]); } //計(jì)算圓上每個(gè)點(diǎn)的坐標(biāo) ///[a]角度[i]刻度[ox]圓心X坐標(biāo)[oy]圓心Y坐標(biāo)[or]圓半徑 function angle(a, i, ox, oy, or) { var hudu = (2 * Math.PI / 360) * a * i;//求出弧度 var x = ox + Math.sin(hudu) * or;//計(jì)算出x軸坐標(biāo)for正弦 var y = oy - Math.cos(hudu) * or;//計(jì)算出y軸坐標(biāo)for余弦 return x + '_' + y; } //畫線方法 ///[ob]繪畫對(duì)象[ox]圓心X坐標(biāo)[oy]圓心Y坐標(biāo)[px]目標(biāo)X坐標(biāo)[py]目標(biāo)Y坐標(biāo) function drawLine(ob, color, ox, oy, px, py) { ob.beginPath(); ob.strokeStyle = color; ob.moveTo(ox, oy); ob.lineTo(px, py); ob.stroke(); ob.closePath(); }<br data-filtered="filtered"> </script> </body> </html>
到此這篇關(guān)于JS在Canvas元素內(nèi)繪制鐘表的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
layui實(shí)現(xiàn)登陸界面驗(yàn)證碼
這篇文章主要為大家詳細(xì)介紹了layui實(shí)現(xiàn)登陸界面驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11完美實(shí)現(xiàn)bootstrap分頁(yè)查詢
這篇文章主要介紹了一個(gè)完美的bootstrap分頁(yè)查詢,如何利用bootstrap實(shí)現(xiàn)分頁(yè)查詢,本文將為大家進(jìn)行揭曉2015-12-12詳解ES6 CLASS在微信小程序中的應(yīng)用實(shí)例
這篇文章主要介紹了詳解ES6 CLASS在微信小程序中的應(yīng)用實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04JS中循環(huán)遍歷數(shù)組的四種方式總結(jié)
這篇文章主要給大家總結(jié)介紹了關(guān)于JS中循環(huán)遍歷數(shù)組的四種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01談?wù)処ntersectionObserver懶加載的具體使用
這篇文章主要介紹了談?wù)処ntersectionObserver懶加載的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10