为了更加熟悉canvas,跟着网上的一些案例,写了一个时钟,随便玩玩,说实话感觉还挺开心,就是个玩。哈哈
代码如下(纯HTML,可以直接运行在浏览器)。
- clock.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.clock-box {
width: 300px;
margin: 100px auto;
}
#dateStr {
text-align: center;
}
</style>
</head>
<body>
<div class="clock-box">
<h1 id="dateStr"></h1>
<canvas id="love_clock_img"></canvas>
</div>
</body>
<script type="text/javascript">
window.onload = function () {
let canvas = document.getElementById('love_clock_img');
let dateStr = document.getElementById('dateStr');
dateStr.innerText = `${new Date().getFullYear()}-${new Date().getMonth() + 1}-${new Date().getDate()}`;
let ctx = canvas.getContext("2d");
let makeClockFun = () => {
// 获取当前时间
let dateMap = new Map(
[
['year', new Date().getFullYear()],
['month', new Date().getMonth() + 1],
['day', new Date().getDate()],
['hour', new Date().getHours()],
['min', new Date().getMinutes()],
['sec', new Date().getSeconds()],
]
);
// 设置 画布大小
canvas.width = 300;
canvas.height = 300;
// 设置 表盘圆心和半径并清理画布
let r = 144;
let pos = [r + 6, r + 6];
ctx.clearRect(0, 0, 300, 300);
// 画大表盘
ctx.beginPath()
ctx.arc(...pos, r, 0, 2 * Math.PI);
ctx.lineWidth = 10;
ctx.strokeStyle = 'black';
ctx.stroke();
ctx.closePath()
ctx.restore();
// 画表芯的装饰 ❤
ctx.beginPath();
ctx.arc(122, 125, 45, 0.8 * Math.PI, 1.9 * Math.PI, false);
ctx.arc(178, 125, 45, 1.1 * Math.PI, 0.2 * Math.PI, false);
ctx.lineTo(150, 220);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
ctx.restore();
// 装饰文字
ctx.fillStyle = '#fff';
ctx.font = '16px Microsoft Yahei';
ctx.beginPath();
ctx.fillText('I love u', 128, 120);
ctx.fill();
ctx.closePath();
// 重新存储 合并画布
ctx.restore();
// 画表盘 刻度
// hourI
let hourI = 0;
while (hourI < 12) {
// 每次都保存
ctx.save();
// 刻度宽度为 4
ctx.lineWidth = 4;
ctx.strokeStyle = "#000";
// 每次把 画布原点的位置 位移到圆心上 并主轴旋转 30度
ctx.translate(...pos);
ctx.rotate(hourI * 30 * Math.PI / 180);
// 开始画刻度
ctx.beginPath();
// 来到纵轴 距离原点 115的位置上,连线画到 135为止。
ctx.moveTo(0, 115);
ctx.lineTo(0, 135);
ctx.stroke();
ctx.closePath();
// 重新存储
ctx.restore();
hourI++;
}
// 画秒针刻度
let secI = 0;
while (secI < 60) {
ctx.save();
ctx.lineWidth = 2;
ctx.strokeStyle = "#000";
ctx.translate(...pos);
ctx.rotate(secI * 6 * Math.PI / 180);
ctx.beginPath();
ctx.moveTo(0, 125);
ctx.lineTo(0, 135);
ctx.stroke();
ctx.closePath();
// 重新存储
ctx.restore();
secI++;
}
// 给小时的刻度标上数字
let num = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
// 刻度数字位置微调数据
let numAdjust = new Map(
[
[3, { x: 0, y: 7 },],
[4, { x: -3, y: 10 }],
[5, { x: -3, y: 9 }],
[6, { x: -6, y: 10 }],
[7, { x: -6, y: 9 }],
[8, { x: -9, y: 8 }],
[9, { x: -12, y: 7 }],
[10, { x: -12, y: 8 }],
[11, { x: -13, y: 7 }],
[12, { x: -11, y: 5 }],
[1, { x: -6, y: 6 }],
[2, { x: -3, y: 4 }],
]
)
let numI = 0;
while (numI < 12) {
// 每次都保存
ctx.save();
ctx.translate(...pos);
ctx.fillStyle = 'red';
ctx.font = '20px Microsoft Yahei';
ctx.beginPath();
let x = (Math.cos((Math.PI / 6) * numI)) * 100 + numAdjust.get(num[numI]).x;
let y = (Math.sin((Math.PI / 6) * numI)) * 100 + numAdjust.get(num[numI]).y;
ctx.fillText(num[numI], x, y);
ctx.fill();
ctx.closePath();
ctx.restore();
numI++;
}
// 根据正常时间画时针,
let hourTemp = dateMap.get('hour') + dateMap.get('min') / 60;
hourTemp = hourTemp > 12 ? hourTemp - 12 : hourTemp;
ctx.save();
ctx.beginPath();
ctx.lineWidth = 1;
ctx.fillStyle = '#000';
ctx.translate(...pos);
ctx.rotate(hourTemp * Math.PI / 6);
ctx.beginPath();
ctx.moveTo(1, 10);
ctx.lineTo(1, -40);
ctx.lineTo(5, -40);
ctx.lineTo(0, -50);
ctx.lineTo(-5, -40);
ctx.lineTo(-1, -40);
ctx.lineTo(-1, 10);
ctx.lineTo(1, 10);
ctx.fill();
ctx.closePath();
// 将之前画的合并起来
ctx.restore();
// 画分针
ctx.save();
ctx.beginPath();
ctx.lineWidth = 1;
ctx.fillStyle = '#000';
ctx.translate(...pos);
ctx.rotate(dateMap.get('min') * Math.PI / 30);
ctx.beginPath();
ctx.moveTo(1, 10);
ctx.lineTo(1, -70);
ctx.lineTo(5, -70);
ctx.lineTo(0, -80);
ctx.lineTo(-5, -70);
ctx.lineTo(-1, -70);
ctx.lineTo(-1, 10);
ctx.lineTo(1, 10);
ctx.fill();
ctx.closePath();
// 将之前画的合并起来
ctx.restore();
// 画秒针
ctx.save();
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'green';
ctx.translate(...pos);
ctx.rotate(dateMap.get('sec') * Math.PI / 30);
ctx.beginPath();
ctx.moveTo(0, 25);
ctx.lineTo(1, -105);
ctx.stroke();
ctx.closePath();
// 装饰 秒针
ctx.beginPath();
ctx.lineWidth = 2;
ctx.fillStyle = 'green';
ctx.arc(1, -95, 4, 0, 2 * Math.PI, false);
ctx.fill();
ctx.closePath();
// 将之前画的合并起来
ctx.restore();
}
setInterval(makeClockFun, 1000);
}
</script>
</html>