最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

使用h5canvas实现时钟的动态效果

来源:懂视网 责编:小采 时间:2020-11-27 15:04:55
文档

使用h5canvas实现时钟的动态效果

使用h5canvas实现时钟的动态效果:canvas 绘制好时钟界面,使用定时器定时重绘整个canvas,就实现了仿真动态时钟的效果。难点在于:秒钟刻度和时钟刻度的绘制整点文字沿着内边圆形环绕其中刻度的环绕并不难计算,文字的环绕就比较坑爹了,canvas绘制的文字是在绘制坐标之上的(文字基线和对齐
推荐度:
导读使用h5canvas实现时钟的动态效果:canvas 绘制好时钟界面,使用定时器定时重绘整个canvas,就实现了仿真动态时钟的效果。难点在于:秒钟刻度和时钟刻度的绘制整点文字沿着内边圆形环绕其中刻度的环绕并不难计算,文字的环绕就比较坑爹了,canvas绘制的文字是在绘制坐标之上的(文字基线和对齐

下图是计算刻度线坐标和整点文字绘制坐标的参考图:

这里写图片描述

canvas画时钟效果的代码编写

下面是全部代码:

<!DOCTYPE html><html lang="en"><head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=1024, height=768,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
 <title>时钟</title></head><body><p style="margin: 50px">
 <canvas width="300" height="300"></canvas>
 <canvas width="200" height="200" style="background-color: #bbbbbb"></canvas>
 <canvas width="200" height="200"></canvas>
 <canvas width="200" height="200"></canvas></p><script>

 var clockHelper = function (canvas, config) {
 if (!config) {
 config = {}
 } var ctx = canvas.getContext('2d'); var deColor = config.deColor ? config.deColor : '#333333'; var deConfig = {
 ringWidth: config.ringWidth ? config.ringWidth : 6,//圆环宽度
 ringColor: config.ringColor ? config.ringColor : deColor,//圆环颜色
 hSaleL: config.hSaleL ? config.hSaleL : 8,//时刻度线长
 hScaleWidth: config.hScaleWidth ? config.hScaleWidth : 4,//时刻度线宽
 hScaleColor: config.hScaleColor ? config.hScaleColor : deColor,//时刻度颜色
 msSaleL: config.msSaleL ? config.msSaleL : 4,//分秒刻度线长
 msScaleWidth: config.msScaleWidth ? config.msScaleWidth : 2,//分秒刻度线宽
 msScaleColor: deColor,//分秒刻度颜色
 hFontSize: config.hFontSize ? config.hFontSize : 18,//整点文字大小
 hHandWidth: config.hHandWidth ? config.hHandWidth : 10,//时针宽度
 mHandWidth: config.mHandWidth ? config.mHandWidth : 5,//分针宽度
 sHandWidth: config.sHandWidth ? config.sHandWidth : 2,//秒针宽度

 hHandColor: config.hHandColor ? config.hHandColor : deColor,//时针颜色
 mHandColor: config.mHandColor ? config.mHandColor : deColor,//分针颜色
 sHandColor: config.sHandColor ? config.sHandColor : '#bb3333',//秒针颜色
 handMode: ['ms', 's'].indexOf("" + config.handMode) !== -1 ? config.handMode : 's',//指针读秒模式,ms:毫秒,s:秒。
 clockFaceColor: config.clockFaceColor ? config.clockFaceColor : '',
 }; var ox = canvas.width / 2; var oy = canvas.height / 2; var width = canvas.width; var height = canvas.height;

 ctx.font = deConfig.hFontSize + "px 黑体"; //中线圆环半径
 var ringR = (width < height) ? (width / 2 - deConfig.ringWidth / 2) : (height / 2 - deConfig.ringWidth / 2); //内圆环半径
 var ringInnerR = (width < height) ? (width / 2 - deConfig.ringWidth) : (height / 2 - deConfig.ringWidth); var timer; var timeSleep = 100; var isStart = false; function start() {
 if (isStart) { return;
 }
 isStart = true; if (deConfig.handMode == 'ms') {
 timeSleep = 100;
 } else {
 timeSleep = 1000;
 }

 ctx.clearRect(0, 0, width, height);
 draw();

 timer = setInterval(function () {
 if (isStart) {
 ctx.clearRect(0, 0, width, height);
 draw();
 }
 }, timeSleep);

 } function stop() {
 isStart = false;
 clearInterval(timer)
 } function draw() {

 beforeDraw();

 drawCircleFace();
 drawHands();

 afterDraw();

 } function drawCircleFace() {

 ctx.fillStyle = deConfig.ringColor;
 ctx.strokeStyle = deConfig.ringColor;

 ctx.lineWidth = deConfig.ringWidth;
 ctx.beginPath();
 ctx.arc(ox, oy, ringR, 0, Math.PI * 2);
 ctx.stroke(); if (deConfig.clockFaceColor) {
 ctx.fillStyle = deConfig.clockFaceColor;
 ctx.fill();
 } var x1 = ox; var y1 = oy; var x2 = ox; var y2 = oy; var radin = 0;
 ctx.lineWidth = deConfig.hScaleWidth; // ctx.beginPath();
 for (var i = 1; i <= 60; i++) {
 radin = i * 6 * Math.PI / 180;
 x1 = ox + ringInnerR * Math.sin(radin);
 y1 = oy - ringInnerR * Math.cos(radin); if (i % 5 === 0) {
 ctx.lineWidth = deConfig.hScaleWidth;
 x2 = ox + (ringInnerR - deConfig.hSaleL) * Math.sin(radin);
 y2 = oy - (ringInnerR - deConfig.hSaleL) * Math.cos(radin);

 ctx.fillStyle = deConfig.hScaleColor; var numText = i / 5 + ""; var textWidth = ctx.measureText(numText).width; var x3 = ox + (ringInnerR - deConfig.hSaleL - deConfig.hFontSize) * Math.sin(radin); var y3 = oy - (ringInnerR - deConfig.hSaleL - deConfig.hFontSize) * Math.cos(radin);
 ctx.textAlign = 'center';
 ctx.textBaseline = 'middle'; //不设置文字居中,基线居中,自己计算。貌似都有误差。因为旋转过程中,角度变化,且文字宽高不尽相同
 // var x3 = ox + (ringInnerR - deConfig.hSaleL - deConfig.hFontSize) * Math.sin(radin) - textWidth / 2;
 // var y3 = oy - (ringInnerR - deConfig.hSaleL - deConfig.hFontSize) * Math.cos(radin) + deConfig.hFontSize/ 2;
 //x2,y2已经求过,化简为:
 // var x3 = x2 - deConfig.hFontSize * Math.sin(radin) - textWidth / 2;
 // var y3 = y2 + deConfig.hFontSize * Math.cos(radin) + textWidth / 2;
 //文字x轴向左偏移一半文字宽,使之水平居中;向下偏移一半高度,使之垂直居中。
 // 实际中发现,字高没法测(api无),而使用fontSize不准。但y轴加上字宽,位置倒是更对齐一些。

 // var x3 = x2 + textWidth / 2;
 // var y3 = y2 - deConfig.hFontSize / 2;

 ctx.fillText(numText, x3, y3);

 } else {
 ctx.lineWidth = deConfig.msScaleWidth;
 x2 = ox + (ringInnerR - deConfig.msSaleL) * Math.sin(radin);
 y2 = oy - (ringInnerR - deConfig.msSaleL) * Math.cos(radin);
 }


 ctx.beginPath();
 ctx.moveTo(x1, y1);
 ctx.lineTo(x2, y2);
 ctx.stroke();

 }

 } //改变坐标中点,并旋转画布也许是更好的选择。
 function drawHands() {
 var date = new Date(); var h = date.getHours() % 12; var m = date.getMinutes(); var s = date.getSeconds(); var ms = date.getMilliseconds(); // console.log(h + ":" + m + ":" + s);
 // 时针

 var hRadin = (h + m / 60 + s / 3600) * Math.PI * 2 / 12; var mRadin = (m + s / 60) * Math.PI * 2 / 60; var sRadin; if (deConfig.handMode == 'ms') {
 sRadin = (s + ms / 1000) * Math.PI * 2 / 60;
 } else {
 sRadin = s * Math.PI * 2 / 60;
 } var x = 0; var y = 0; var hDotR = deConfig.hHandWidth + 2; var mDotR = 0.6 * hDotR var sDotR = 0.5 * hDotR //秒针半径
 var sHandR = ringInnerR - deConfig.hSaleL * 2
 //分针半径
 var mHandR = 0.8 * sHandR; //时针半径
 var hHandR = 0.7 * mHandR; //时针
 ctx.beginPath();
 ctx.lineWidth = deConfig.hHandWidth;
 ctx.strokeStyle = deConfig.hHandColor;
 ctx.strokeStyle = deConfig.hHandColor;
 ctx.moveTo(ox, oy);
 x = ox + hHandR * Math.cos(hRadin - Math.PI / 2);
 y = oy + hHandR * Math.sin(hRadin - Math.PI / 2);
 ctx.lineTo(x, y);
 ctx.stroke(); //针尖。直接圆型了(矩形指针来绘制针尖,计算复杂。。)
 ctx.beginPath();
 ctx.lineWidth = 0;
 ctx.arc(x, y, deConfig.hHandWidth / 2, 0, 2 * Math.PI);
 ctx.fill(); //中心
 ctx.beginPath(); // ctx.lineWidth = hDotR;
 ctx.arc(ox, oy, hDotR / 2, 0, Math.PI * 2);
 ctx.fill();
 ctx.stroke(); //分针
 ctx.beginPath();
 ctx.lineWidth = deConfig.mHandWidth;
 ctx.strokeStyle = deConfig.mHandColor;
 ctx.fillStyle = deConfig.mHandColor;
 ctx.moveTo(ox, oy);
 x = ox + mHandR * Math.cos(mRadin - Math.PI / 2);
 y = oy + mHandR * Math.sin(mRadin - Math.PI / 2);
 ctx.lineTo(x, y);
 ctx.stroke(); //针尖。直接圆型了(矩形指针来绘制针尖,计算复杂。。)
 ctx.beginPath();
 ctx.lineWidth = 0;
 ctx.arc(x, y, deConfig.mHandWidth / 2, 0, 2 * Math.PI);
 ctx.fill(); //中心
 ctx.beginPath();
 ctx.arc(ox, oy, mDotR / 2, 0, Math.PI * 2);
 ctx.stroke(); //秒针
 ctx.beginPath();
 ctx.strokeStyle = deConfig.sHandColor;
 ctx.fillStyle = deConfig.sHandColor;
 ctx.lineWidth = deConfig.sHandWidth; //秒针有长短两线
 x = ox - sHandR / 4 * Math.cos(sRadin - Math.PI / 2);
 y = oy - sHandR / 4 * Math.sin(sRadin - Math.PI / 2);
 ctx.moveTo(x, y);
 x = ox + sHandR * Math.cos(sRadin - Math.PI / 2);
 y = oy + sHandR * Math.sin(sRadin - Math.PI / 2);
 ctx.lineTo(x, y);
 ctx.stroke(); //针尖。直接圆型了(矩形指针来绘制针尖,计算复杂。。)
 ctx.beginPath();
 ctx.lineWidth = 0;
 ctx.arc(x, y, deConfig.sHandWidth / 2, 0, 2 * Math.PI);
 ctx.fill(); //中心
 ctx.beginPath();
 ctx.fillStyle = deColor;
 ctx.arc(ox, oy, sDotR, 0, Math.PI * 2);
 ctx.fill();
 ctx.stroke();

 } function beforeDraw() {
 if (typeof exp.beforeDraw === 'function') {
 exp.beforeDraw(ctx, deConfig);
 }
 } function afterDraw() {
 if (typeof exp.afterDraw === 'function') {
 exp.afterDraw(ctx, deConfig);
 }
 } var exp = {
 start: start,
 stop: stop,
 beforeDraw: null,
 afterDraw: null,
 } return exp;


 } var clockCanvas1 = document.getElementsByTagName('canvas')[0]; var clockCanvas2 = document.getElementsByTagName('canvas')[1]; var clockCanvas3 = document.getElementsByTagName('canvas')[2]; var clockCanvas4 = document.getElementsByTagName('canvas')[3]; var clock = clockHelper(clockCanvas1, {mHandColor: '#3333bb', sHandColor: '#bb3333'});
 clock.start();
 setTimeout(function () {
 clock.stop()
 }, 5000)
 setTimeout(function () {
 clock.start();
 }, 8000)

 clockHelper(clockCanvas2, {
 mHandColor: 'green',
 hHandWidth: 6,
 mHandWidth: 4,
 hFontSize: 14,
 hScaleWidth: 2,
 handMode: 'ms'
 }).start();


 clockHelper(clockCanvas2, {
 mHandColor: 'green',
 hHandWidth: 6,
 mHandWidth: 4,
 hFontSize: 14,
 hScaleWidth: 2,
 handMode: 'ms'
 }).start();


 clockHelper(clockCanvas3, {
 deColor: '#bbbbbb',
 sHandColor: '#bbbbbb',
 clockFaceColor: '#112233',//钟面
 hHandWidth: 6,
 mHandWidth: 4,
 hFontSize: 14,
 hScaleWidth: 2,
 handMode: 's'
 }).start(); var clock4 = clockHelper(clockCanvas4, {
 deColor: '#bbbbbb',
 sHandColor: '#bbbbbb', // clockFaceColor: '#112233',
 hHandWidth: 6,
 mHandWidth: 4,
 hFontSize: 14,
 hScaleWidth: 2,
 handMode: 's'
 });

 clock4.afterDraw = function (ctx, deConfig) {
 var grd = ctx.createLinearGradient(0, 0, clockCanvas4.width, clockCanvas4.height);
 grd.addColorStop(0, "rgba(255,0,0,0.3)");
 grd.addColorStop(1, "rgba(0,0,255,0.5)");
 ctx.fillStyle = grd;
 ctx.arc(clockCanvas4.width/2,clockCanvas4.height/2,clockCanvas4.width/2,0,Math.PI*2); // ctx.fillRect(0, 0, clockCanvas4.width, clockCanvas4.height);
 ctx.fill();

 ctx.fillText('时钟绘制完成后,自定义其他绘制',clockCanvas4.width/2,clockCanvas4.height - deConfig.hFontSize);
 };

 clock4.start();</script></body></html>

说明:

1、clockHelper第一个参数传入画布。第二个参数传入时钟界面的配置对象,包括指针、刻度的颜色、大小等,配置项和clockHelper中的deConfig默认对象是相对的,参考deConfig的属性传入参数即可。

2、clockHelper的封装性略差,仅是基本能用型。但属性不多,改造应该并不困难。

3、提供了时钟界面绘制之前和之后的方法,可以在beforeDraw和afterDraw这两个方法中执行自己的逻辑。但是由于事先设计没有留出足够的空白像素,用处不大。只能进行一些简单的再绘制。比如给钟面添加色彩、渐变。

文档

使用h5canvas实现时钟的动态效果

使用h5canvas实现时钟的动态效果:canvas 绘制好时钟界面,使用定时器定时重绘整个canvas,就实现了仿真动态时钟的效果。难点在于:秒钟刻度和时钟刻度的绘制整点文字沿着内边圆形环绕其中刻度的环绕并不难计算,文字的环绕就比较坑爹了,canvas绘制的文字是在绘制坐标之上的(文字基线和对齐
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top