Canvas 绘制一个粉色时钟

49 阅读2分钟

我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

前言

工作中不常使用canvas,都忘记这是个啥了,知识都需要反复学习、使用,才会有所记忆,因此今天来实现一个时钟,回忆一下canvas的基本使用

具体实现

  1. 用canvas标签创建一个300*300的画布。并使用css控制水平方向居中显示
<canvas id="canvas" width="300" height="300"></canvas>
  1. 获取画布对象,构建环境
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
  1. 设置中心点

通过translate方法把原点移动到画布的中心(150, 150),后面绘图都会基于这个中心点绘制

// 清除整个画布  因为每次画的时针、分针等,都会保留,所以要清空
ctx.clearRect(0, 0, 300, 300);
ctx.save();
// translate() 方法, 将 canvas 按原始 x点的水平方向、原始的 y点垂直方向进行平移变换
// 设置中心点
ctx.translate(150, 150);

ctx.save()存储当前canvas的状态

  1. 绘制时钟的形状(半径为105px的圆形)
ctx.beginPath();
ctx.lineWidth = 10;
// 画圆线使用arc(中心点X,中心点Y,半径,起始角度,结束角度)
ctx.arc(0, 0, 105, 0, 2 * Math.PI);
ctx.strokeStyle="#f6cec1";
// 执行画线段的操作stroke
ctx.stroke();
ctx.closePath();

canvas里的角度是以PI(π)为单位的,在js中写作Math.PI,可以把一个PI理解为180度

  1. 绘制时钟的刻度线

60s的刻度 => 60个刻度线

12h的刻度 => 12个刻度线

// 绘制刻度
ctx.lineWidth = 1;
for (let i = 0; i < 60; i++) {
    ctx.rotate(2 * Math.PI / 60);
    ctx.beginPath();
    ctx.moveTo(95, 0);
    ctx.lineTo(100, 0);
    ctx.stroke();
    ctx.closePath();
}
// 恢复画笔
ctx.restore();
ctx.save();
ctx.lineWidth = 2.5;
for (let i = 0; i < 12; i++) {
    ctx.rotate(2 * Math.PI / 12);
    ctx.beginPath();
    ctx.moveTo(92, 0);
    ctx.lineTo(100, 0);
    ctx.stroke();
    ctx.closePath();
}
ctx.restore();      
  1. 绘制时钟的刻度代表小时的刻度数字
//刻度数字
ctx.save();
ctx.font = '14px Arial';
ctx.fillStyle = '#333';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
for (let i = 1; i <= 12; i++) {
const rad = ((i - 3) * (Math.PI * 2)) / 12;
const x = 95 * 0.85 * Math.cos(rad);
const y = 95 * 0.85 * Math.sin(rad);
ctx.fillText(i, x, y);
}
ctx.restore();

Math 对象里面的 sin() 和 cos() 方法使用的是弧度。rad获取数字之间相应弧度

cxt.textAlign = "center" 和 cxt.textBaseline = "middle"设置文本的垂直居中对齐,不设置将会导致小时数字的偏移

  1. 获取当前时间
let time = new Date()
let hour = time.getHours() % 12
let min = time.getMinutes()
let sec = time.getSeconds()
  1. 绘制时钟时针
// 时针 默认情况下一条线指向的是三点钟方向,减去90°指针指向12点钟方向,然后才计算实际时间所在方位
ctx.rotate(2 * Math.PI / 12 * hour + 2 * Math.PI / 12 * (min / 60) - Math.PI / 2);
ctx.beginPath();
// moveTo设置画线起点
ctx.moveTo(0, 0);
// lineTo设置画线经过点
ctx.lineTo(40, 0);
// 设置线宽
ctx.lineWidth = 5;
// 针头为圆角
ctx.lineCap = "round";
ctx.strokeStyle = "black";
ctx.stroke();
ctx.closePath();
// 恢复成上次save的状态
ctx.restore();
// 恢复完再保存一次
ctx.save();
  1. 绘制时钟分针
ctx.rotate(2 * Math.PI / 60 * min + 2 * Math.PI / 60 * (sec / 60) - Math.PI / 2);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(60, 0);
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.strokeStyle = "black";
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
  1. 绘制时钟秒针
ctx.rotate(2 * Math.PI / 60 * sec - Math.PI / 2);
ctx.beginPath();
ctx.moveTo(-10, 0);
ctx.lineTo(80, 0);
ctx.lineWidth = 1;
ctx.lineCap = "round";
ctx.strokeStyle = 'red';
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();

最后添加一个定时器setInterval,让时钟运行起来,显示实时时间

代码块展示

code.juejin.cn/pen/7146577…