使用canvas实现另一个小时钟,效果图如下:
前端html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
body {
background: #dddddd;
}
#canvas {
margin: 0 auto;
padding: 10px;
background:#ffffff;
border: thin inset #aaaaaa;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400">
Canvas not supported
</canvas>
<script src="./js/example.js"></script>
</body>
</html>
下面是example.js的具体实现:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var FONT_HEIGHT = 15;// 字体大小
var MARGIN = 35; // 边距
var HAND_TRUNCATION = canvas.width/12; // 分钟需要减去的半径
var HOUR_HAND_TRUNCATION = canvas.width/10;// 小时针需要减去的半径
var NUMBER_SPACING = 20; // 数字间距
var RADIUS = canvas.width/2 - MARGIN; // 半径
var HAND_RADIUS = RADIUS + NUMBER_SPACING; // 指针半径(数字间距)
// 绘制圆
function drawCircle(){
context.beginPath();
context.arc(canvas.width/2, canvas.height/2, RADIUS, 0, Math.PI*2, true);
context.stroke();
}
// 绘制中心点
function drawCenter(){
context.beginPath();
context.arc(canvas.width/2, canvas.height/2, 5, 0, Math.PI*2, true);
context.fill();
}
// 绘制数字
function drawNumbers(){
var numberals = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var angle = 0;
var numeralWidth = 0;
numberals.forEach(function(numeral){
angle = Math.PI/6 * (numeral - 3);
// 填充文字
numeralWidth = context.measureText(numeral).width;
context.fillText(numeral,
canvas.width/2 + Math.cos(angle)*(HAND_RADIUS)
- numeralWidth/2,
canvas.height/2 + Math.sin(angle)*(HAND_RADIUS)
+ FONT_HEIGHT/3
);
// 绘制刻度
context.moveTo(canvas.width/2 + Math.cos(angle)*(RADIUS -5),
canvas.height/2 + Math.sin(angle)*(RADIUS -5));
context.lineTo(canvas.width/2 + Math.cos(angle)*(RADIUS),
canvas.height/2 + Math.sin(angle)*(RADIUS));
context.stroke();
});
}
// 绘制指针
function drawHand(loc, isHour , isMin){
var angle = (Math.PI * 2) * (loc/60) - Math.PI/2;
var handRadius = isHour? RADIUS - HAND_TRUNCATION - HOUR_HAND_TRUNCATION
: (isMin ? (RADIUS - HAND_TRUNCATION) : (RADIUS * 0.95));
context.moveTo(canvas.width/2, canvas.height/2);
context.lineTo(canvas.width/2 + Math.cos(angle) * handRadius,
canvas.height/2 + Math.sin(angle) * handRadius);
context.stroke();
}
// 绘制所有指针
function drawHands(){
var date = new Date;
var hour = date.getHours();
hour = hour >12 ? hour - 12 : hour;
// 绘制小时指针
drawHand((hour + date.getMinutes()/60)*5, true,false);
// 绘制分钟指针
drawHand(date.getMinutes(),false,true);
// 绘制秒指针
drawHand(date.getSeconds(),false,false);
}
// 画钟
function drawClock(){
context.clearRect(0, 0, canvas.width, canvas.height);
drawCircle();
drawCenter();
drawNumbers();
drawHands();
}
context.font = FONT_HEIGHT + 'px Arial';
loop = setInterval(drawClock, 1000);
另外,实现时钟的主要的难点如下:
在刻画指针的时候采用了这样的处理方法:
小时取1-12 但是我们会乘以5,因为我们把一个圆分成了60个小刻度,这样在渲染的时候对于时、分、秒的处理就变得很容易:
时指针的偏移度数(我们取canvas下的偏转度数)={ [ (小时数 + 当前时间的分钟/60) * 5] / 60 } * (2 * π) - π/2。
具体理解如下:
首先我们以canvas旋转坐标定义,顺时针为+,逆时针为-,这样我们回归到0度数。假设现在需要渲染1:00,小时指针情况,显然1个小时占据圆盘的30度的夹角,我们从0开始旋转30度角成:
但是实际上1:00的表盘时指针的显示应该为: