JS在Canvas元素内绘制钟表
首先,canvas语法基础薄弱的小伙伴请点这里,剩下的小伙伴们可以接着往下看了。
一个表,需要画什么出来呢:3条线(时分秒针),1个圆(表盘),以及60条短线/点(刻度)。
嗯,没毛病。
那接下来让我们考虑点细节:一个圆,自然是360°,分成60个刻度,两个刻度之间相隔6°,然后分针和秒针刻度偏移是相同的,时针的刻度偏移应该是它们的5倍(只有12个小时刻度)=30°,然而你见过时分秒针一样长的表么?(我反正没有)所以我们还需要控制它们的长度是不一样的才对。
咳,有了上面的思考作为基础了,开搞。
先定个点画个圆:
var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.arc(X坐标, Y坐标, 半径, 0, 2 * Math.PI, false); ctx.strokeStyle = 随便填颜色; ctx.stroke(); ctx.closePath();
接下来我们要打上时间刻度,可是问题来了:你是可以画出来一个圆,也知道每个刻度6°角,可如何在画出来的圆上找到对应的坐标呢?
don't worry(数学知识过关的小伙伴们表示毫无压力)~我们只需要去算出正余弦就拿到了对应的XY坐标啦(是的,脚本内正余弦算法不是算角度),具体做法如下:
//计算圆上每个点的坐标 ///[a]角度[i]刻度[ox]圆心X坐标[oy]圆心Y坐标[or]圆半径 function angle(a, i, ox, oy, or) { var hudu = (2 * Math.PI / 360) * a * i;//求出弧度 var x = ox + Math.sin(hudu) * or;//计算出x轴坐标for正弦 var y = oy - Math.cos(hudu) * or;//计算出y轴坐标for余弦 return x + '_' + y; }
到了这里,我们就可以愉快的画刻度了:
//打上文字(仅小时) for (var i = 0; i < 12; i++) { var textXY = angle(30, i + 1, ox, oy, or - 10);//小时刻度坐标 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);//分、秒刻度坐标 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(); }
为了逼真,我还加入了秒针影响分针,分针影响秒针的计算。(见最后代码)
然后就是考虑三根针不一样长的问题,这个问题试过很多遍,最后我发现最简单的解决办法就是多画3个圆,因为偏移的角度计算方式是一样的。
最后的结果是这样的:
因为不支持上传html文件,所以我就把所有代码贴在这里了:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>小马的canvas练手作品-时钟</title> <meta charset="utf-8" /> </head> <body> <canvas id="myCanvas" width="1000" height="1000">您的浏览器不支持此标签</canvas> <script type="text/javascript"> setInterval('drawClock(150, 150, 100, 50, 70, 90,"pink","black","red","green")', 1000); //画钟表 //[ox]圆心X坐标[oy]圆心Y坐标[or]钟表半径[hr]时针半径[mr]分针半径[sr]秒针半径[oc]钟表外环颜色[hc]时针颜色[mc]分针颜色[sc]秒针颜色 function drawClock(ox, oy, or, hr, mr, sr, oc, hc, mc, sc) { //时钟底盘 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(); //获取当前时间 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);//显示月日 //打上时间刻度 for (var i = 0; i < 12; i++) { var textXY = angle(30, i + 1, ox, oy, or - 10);//小时刻度坐标 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);//分、秒刻度坐标 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;//分钟影响时针偏移 var hoursXY = angle(30, h > 12 ? h - 12 : h, ox, oy, hr);//时针终点XY坐标 drawLine(ctx, hc, ox, oy, hoursXY.split('_')[0], hoursXY.split('_')[1]); m = m + s / 60;//秒钟影响分针偏移 var minuteXY = angle(6, m, ox, oy, mr);//分针终点XY坐标 drawLine(ctx, mc, ox, oy, minuteXY.split('_')[0], minuteXY.split('_')[1]); var secondXY = angle(6, s, ox, oy, sr);//秒针终点XY坐标 drawLine(ctx, sc, ox, oy, secondXY.split('_')[0], secondXY.split('_')[1]); } //计算圆上每个点的坐标 ///[a]角度[i]刻度[ox]圆心X坐标[oy]圆心Y坐标[or]圆半径 function angle(a, i, ox, oy, or) { var hudu = (2 * Math.PI / 360) * a * i;//求出弧度 var x = ox + Math.sin(hudu) * or;//计算出x轴坐标for正弦 var y = oy - Math.cos(hudu) * or;//计算出y轴坐标for余弦 return x + '_' + y; } //画线方法 ///[ob]绘画对象[ox]圆心X坐标[oy]圆心Y坐标[px]目标X坐标[py]目标Y坐标 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>
上一篇:微信小程序map地图使用方法详解
栏 目:JavaScript代码
下一篇:JS随机密码生成算法
本文标题:JS在Canvas元素内绘制钟表
本文地址:http://www.codeinn.net/misctech/192985.html