效果展示:
源码展示:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>canvas绘制时钟</title>
<style>
* {
margin:0;
padding:0;
}
canvas {
display:block;
margin:200px auto;
}
</style>
</head>
<body>
<canvas id="clock" width="200px" height="200px"></canvas>
<script>
var dom = document.getElementById('clock');
var ctx = dom.getContext('2d');
var width = ctx.canvas.width;
var height = ctx.canvas.height;
var r = width / 2;
var rem = width / 200;
//无论canvas画布多大 时钟都会随着比例变化
function drawBackground() {
ctx.save();
//保存当前画布 以便使用clearRect()
/*****************绘制背景圆****************************/
ctx.translate(r, r);
//把绘图的中心移动到坐标为(r,r)的位置
ctx.beginPath();
//开始绘图
ctx.lineWidth = 10 * rem;
//线条宽度
ctx.arc(0, 0, r - ctx.lineWidth / 2, 0, 2 * Math.PI, false);
//绘制一个圆坐标为刚刚移动到的位置 因为半径为canvas正方形的一半所以半径要减去线条宽度的一半
ctx.stroke();
//绘制
/****************绘制小时点********************************/
var hourNumber = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
//定义一个小时点数组 因为圆的起点是90度那个位置开始的
ctx.font = 18 * rem + 'px Arial';
//设置字体大小
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
//设置文本的对齐方式 文本对齐居中 文本基线居中对齐
hourNumber.forEach(function(number, i) { //遍历并获取该数组 传入参数 一个为数字 一个是索引
var rad = 2 * Math.PI / 12 * i;
//定义弧度 12个数字 相差就是 2*Math.PI / 12 这就是每个小时数的弧度 再乘以索引以对应弧度的计算
var x = Math.cos(rad) * (r - 30 * rem);
//求x坐标 用cos方法 在乘以半径 因为小时点的半径肯定会小一些所以就半径也要小一点
var y = Math.sin(rad) * (r - 30 * rem);
//求y坐标 方法同上
ctx.fillText(number, x, y);
//填充文本 第一个参数是 文本 第二,三个为坐标
});
/************绘制分钟点**********************/
for (var i = 0; i < 60; i++) {
//利用for循环遍历60个点
var rad = 2 * Math.PI / 60 * i;
//定义弧度60个点
var x = Math.cos(rad) * (r - 18 * rem);
//定义x坐标的位置 方法同上
var y = Math.sin(rad) * (r - 18 * rem);
//定义y坐标的位置 方法同上
ctx.beginPath();
//因为上面有过beginPath所以需要重新绘制
if (i % 5 === 0) {
//因为小时点是每隔5个就有一个所以 如果i取余等于0 就是小时数 小时点的样式带啊如下
ctx.fillStyle = "black"
ctx.arc(x, y, 2 * rem, 0, 2 * Math.PI, false);
//绘制圆 半径为2像素
} else {
//反过来就是这样
ctx.fillStyle = "#ccc";
ctx.arc(x, y, 2 * rem, 0, 2 * Math.PI, false);
//绘制圆 半径为2像素
}
ctx.fill();
//因为需要实心圆 所以需要填充
}
}
/****************绘制时针*************/
function drawHour(hour, minute) {
//绘制时针
ctx.save();
//save()和restore连用 表示先将其绘图环境保存起来 restore返回之前保存的状态
ctx.beginPath();
var rad = 2 * Math.PI / 12 * hour;
//设置时针的位置 定义弧度
var mrad = 2 * Math.PI / 12 / 60 * minute;
//因为时间在4:30的时候时针应该会在4-5之间 所以我们需要计算其当时的弧度
ctx.rotate(rad + mrad);
//旋转至该弧度 加上分针中间的弧度 所以时针的弧度等于 时针的弧度加上分针的弧度
ctx.lineCap = 'round';
//绘制线条为圆头
ctx.lineWidth = 5 * rem;
ctx.moveTo(0, 10 * rem);
//移动圆点 因为时针需要多点尾巴出来所以定义到10;
ctx.lineTo(0, -r / 2);
//添一个点,将其链接到这个位置
ctx.stroke();
ctx.restore();
}
/*************绘制分针******************/
function drawMinute(minute) {
//绘制分针方法与时针方法类似
ctx.save();
ctx.beginPath();
var rad = 2 * Math.PI / 60 * minute;
ctx.rotate(rad);
ctx.lineWidth = 3 * rem;
ctx.lineCap = 'round';
ctx.moveTo(0, 10 * rem);
ctx.lineTo(0, -r + 30 * rem);
ctx.stroke();
ctx.restore();
}
/*******绘制秒针****************/
function drawSecond(second) {
ctx.save();
ctx.beginPath();
ctx.fillStyle = '#f00';
var rad = 2 * Math.PI / 60 * second;
ctx.rotate(rad);
ctx.moveTo(-2 * rem, 20 * rem);
//绘制秒针的线条 一头大 一头小
ctx.lineTo(2 * rem, 20 * rem);
ctx.lineTo(1, -r + 18 * rem);
ctx.lineTo(-1, -r + 18 * rem);
ctx.fill();
//绘制线条颜色
ctx.restore();
}
/************绘制中心圆点*************/
function drawDot() {
ctx.beginPath();
ctx.fillStyle = "#fff";
ctx.arc(0, 0, 3 * rem, 0, 2 * Math.PI, false);
ctx.fill();
}
function draw() {
ctx.clearRect(0, 0, width, height);
//设置计时器每秒调用一次 但是因为调用后 之前的还会存在所以需要每秒清除画布
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
drawBackground();
drawHour(hour, minute);
drawMinute(minute);
drawSecond(second);
drawDot();
ctx.restore();
}
setInterval(draw, 1000);
</script>
</body>
</html>