Canvas学习-时钟绘制
Canvas学习-时钟绘制
1. 绘制时钟外边框
创建画布
备注:该容器就是绘制图形的画布。
绘制圆环
var dom = document.getElementById(‘clock’); //获取元素
var ctx = dom.getContext(‘2d’); //上下文
var width = ctx.canvas.width; //上下文的宽度
var height = ctx.canvas.height; //上下文的高度
var r = width / 2; //半径// 绘制圆环
function drawBackground() {ctx.translate(r, r); //确定坐标远点
ctx.beginPath(); //开始画图
ctx.lineWidth = 10; // 设置线条粗细
ctx.arc(0, 0, r-5, 0, 2 * Math.PI, false); //绘制圆形
ctx.stroke(); //绘制
}
drawBackground();
2.绘制时钟内容
// 绘制小时数
var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
ctx.font = '18px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
hourNumbers.forEach(function (number, i) {
var rad = 2 * Math.PI / 12 * i;
var x = Math.cos(rad) * (r - 30);
var y = Math.sin(rad) * (r - 30);
ctx.fillText(number, x, y);
})
备注:在绘制小时数的时候,我们应该确定数字与对应弧度的关系,建立数组,填充数字。
3. 绘制小时数对应的圆点
// 绘制小时数对应的点
for (var i = 0; i < 60; i++) {
var rad = 2 * Math.PI / 60 * i;
var x = Math.cos(rad) * (r - 18);
var y = Math.sin(rad) * (r - 18);
ctx.beginPath();
if (i % 5 === 0) {
ctx.fillStyle = "#000";
ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
} else {
ctx.fillStyle = "#ccc";
ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
}
ctx.fill();
}
备注:绘制圆点的时候,我们需要区分整点数与非整点数之间的区别,填充不同的背景颜色。
4.绘制是真分针秒针
// 画时针
function drawHour(hour, minute) {
ctx.save();
ctx.beginPath();
var rad = 2 * Math.PI / 12 * hour;
var mrad = 2 * Math.PI / 12 / 60 * minute;
ctx.rotate(rad + mrad);
ctx.lineWidth = 6;
ctx.lineCap = 'round';
ctx.moveTo(0, 10);
ctx.lineTo(0, -r / 2);
ctx.stroke();
ctx.restore();
}
// 画分针
function drawMinute(minute, second) {
ctx.save();
ctx.beginPath();
var rad = 2 * Math.PI / 60 * minute;
var srad = 2 * Math.PI / 60 / 60 * second;
ctx.rotate(rad + srad);
ctx.lineWidth = 3;
ctx.lineCap = 'round';
ctx.moveTo(0, 10);
ctx.lineTo(0, -r + 30);
ctx.stroke();
ctx.restore();
}
// 画秒针
function drawSecond(second) {
ctx.save();
ctx.beginPath();
ctx.fillStyle = '#c14543';
var rad = 2 * Math.PI / 60 * second;
ctx.rotate(rad);
ctx.moveTo(-2, 20);
ctx.lineTo(2, 20);
ctx.lineTo(1, -r + 18);
ctx.lineTo(-1, -r + 18);
ctx.lineTo(0, -r + 30);
ctx.fill();
ctx.restore();
}
备注:绘制分针的时候,我们需要考虑到分针对其的影响,所以需要计算分针数引起时针的弧度改变。在绘制分针的时候,同样需要考虑秒针对分针的影响。
4. 画中心点
// 画中心点
function drawDot() {
ctx.beginPath();
ctx.fillStyle = '#FFFFFF';
ctx.arc(0, 0, 3, 2 * Math.PI, false)
ctx.fill();
}
5. 最终绘制方法
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, second);
drawSecond(second);
drawDot();
ctx.restore();
}
draw();
setInterval(draw, 1000);
备注:在绘制图形的时候,我们需要注意一下几点:
- 绘制之前,我们需要清除画布,避免图形的叠加。
- 主要保存画布之前的状态,还原状态,避免影响。
- 利用定时器,每隔一秒钟,重新绘制图片。
6. 效果图
7. 代码
var dom = document.getElementById('clock'); //获取元素
var ctx = dom.getContext('2d'); //上下文
var width = ctx.canvas.width; //上下文的宽度
var height = ctx.canvas.height; //上下文的高度
var r = width / 2; //半径
// 绘制圆环
function drawBackground() {
ctx.save();
ctx.translate(r, r); //确定坐标远点
ctx.beginPath(); //开始画图
ctx.lineWidth = 10; // 设置线条粗细
ctx.arc(0, 0, r - 5, 0, 2 * Math.PI, false); //绘制圆形
ctx.stroke(); //绘制
// 绘制小时数
var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
ctx.font = '18px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
hourNumbers.forEach(function (number, i) {
var rad = 2 * Math.PI / 12 * i;
var x = Math.cos(rad) * (r - 30);
var y = Math.sin(rad) * (r - 30);
ctx.fillText(number, x, y);
})
// 绘制小时数对应的点
for (var i = 0; i < 60; i++) {
var rad = 2 * Math.PI / 60 * i;
var x = Math.cos(rad) * (r - 18);
var y = Math.sin(rad) * (r - 18);
ctx.beginPath();
if (i % 5 === 0) {
ctx.fillStyle = "#000";
ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
} else {
ctx.fillStyle = "#ccc";
ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
}
ctx.fill();
}
}
// 画时针
function drawHour(hour, minute) {
ctx.save();
ctx.beginPath();
var rad = 2 * Math.PI / 12 * hour;
var mrad = 2 * Math.PI / 12 / 60 * minute;
ctx.rotate(rad + mrad);
ctx.lineWidth = 6;
ctx.lineCap = 'round';
ctx.moveTo(0, 10);
ctx.lineTo(0, -r / 2);
ctx.stroke();
ctx.restore();
}
// 画分针
function drawMinute(minute, second) {
ctx.save();
ctx.beginPath();
var rad = 2 * Math.PI / 60 * minute;
var srad = 2 * Math.PI / 60 / 60 * minute;
ctx.rotate(rad + srad);
ctx.lineWidth = 3;
ctx.lineCap = 'round';
ctx.moveTo(0, 10);
ctx.lineTo(0, -r + 30);
ctx.stroke();
ctx.restore();
}
// 画秒针
function drawSecond(second) {
ctx.save();
ctx.beginPath();
ctx.fillStyle = '#c14543';
var rad = 2 * Math.PI / 60 * second;
ctx.rotate(rad);
ctx.moveTo(-2, 20);
ctx.lineTo(2, 20);
ctx.lineTo(1, -r + 18);
ctx.lineTo(-1, -r + 18);
ctx.lineTo(0, -r + 30);
ctx.fill();
ctx.restore();
}
// 画中心点
function drawDot() {
ctx.beginPath();
ctx.fillStyle = '#FFFFFF';
ctx.arc(0, 0, 3, 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, second);
drawSecond(second);
drawDot();
ctx.restore();
}
draw();
setInterval(draw, 1000);
8. 思考
如果画布放大,那么图像会怎么样呢?显然,因为其中部分数据大小是固定写死的,必然出现不协调的地方,此时我们必须考虑到,数据的比例问题。修改思路如下:在宽度、文字大小部分,我们需要采用相对大小。
9. 代码优化
优化思路:首先确定比例,var rem = width/ 200; //比例(因为初始样式的数据是按照200为基准的)
,然后在对应的数字大小部分乘上该比例即可。修改后的代码如下:
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; //比例(因为初始样式的数据是按照200为基准的)
// 绘制圆环
function drawBackground() {
ctx.save();
ctx.translate(r, r); //确定坐标远点
ctx.beginPath(); //开始画图
ctx.lineWidth = 10 * rem; // 设置线条粗细
ctx.arc(0, 0, r - ctx.lineWidth/2, 0, 2 * Math.PI, false); //绘制圆形
ctx.stroke(); //绘制
// 绘制小时数
var hourNumbers = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
ctx.font = 18* rem + 'px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
hourNumbers.forEach(function (number, i) {
var rad = 2 * Math.PI / 12 * i;
var x = Math.cos(rad) * (r - 30* rem);
var y = Math.sin(rad) * (r - 30* rem);
ctx.fillText(number, x, y);
})
// 绘制小时数对应的点
for (var i = 0; i < 60; i++) {
var rad = 2 * Math.PI / 60 * i;
var x = Math.cos(rad) * (r - 18* rem);
var y = Math.sin(rad) * (r - 18* rem);
ctx.beginPath();
if (i % 5 === 0) {
ctx.fillStyle = "#000";
ctx.arc(x, y, 2* rem, 0, 2 * Math.PI, false);
} else {
ctx.fillStyle = "#ccc";
ctx.arc(x, y, 2* rem, 0, 2 * Math.PI, false);
}
ctx.fill();
}
}
// 画时针
function drawHour(hour, minute) {
ctx.save();
ctx.beginPath();
var rad = 2 * Math.PI / 12 * hour;
var mrad = 2 * Math.PI / 12 / 60 * minute;
ctx.rotate(rad + mrad);
ctx.lineWidth = 6* rem;
ctx.lineCap = 'round';
ctx.moveTo(0, 10* rem);
ctx.lineTo(0, -r / 2);
ctx.stroke();
ctx.restore();
}
// 画分针
function drawMinute(minute, second) {
ctx.save();
ctx.beginPath();
var rad = 2 * Math.PI / 60 * minute;
var srad = 2 * Math.PI / 60 / 60 * second;
ctx.rotate(rad + srad);
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 = '#c14543';
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 = '#FFFFFF';
ctx.arc(0, 0, 3* rem, 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, second);
drawSecond(second);
drawDot();
ctx.restore();
}
draw();
setInterval(draw, 1000);
10. 代码下载
链接:canvas学习代码下载
还没有评论,来说两句吧...