Html5 canvas 钟表 实现代码如下: 复制代码<html><head> <title>Html5 canvas 钟表</title> <style type...
Html5 canvas 钟表 实现代码如下:
复制代码
<html>
<head>
<title>Html5 canvas 钟表</title>
<style type="text/css">
canvas{ border:2px solid Gray; background-color:Gray;}
</style>
</head>
<body>
<canvas></canvas>
<script type="text/javascript">
//时钟对象
function clock(canvasID) {
var TT = new Date();
var HH = TT.getHours();
//时,分,秒
this.HH = HH > 12 ? HH - 12 : HH;
this.MM = TT.getMinutes();
this.SS = TT.getSeconds();
var canvas = document.getElementById(canvasID);
this.context = canvas.getContext("2d");
//宽,高,半径,表盘外边框宽度,品牌文字
this.W = canvas.offsetWidth;
this.H = canvas.offsetHeight;
this.R = this.W / 2;
this.B = 12;
this.Brand = "SIMILAR";
}
//初始化设置
clock.prototype.cxtInit = function () {
var cxt = this.context;
cxt.save(); //保存画布原始状态
cxt.lineWidth = 3; //笔刷宽度为3
cxt.strokeStyle = "White"; //笔刷颜色为白色
cxt.translate(this.R, this.R); //定位中心点
cxt.rotate(-Math.PI / 2); //旋转负90度
cxt.save(); //保存初始化设置后的状态
}
//画表盘
clock.prototype.drawCCFace = function () {
var cxt = this.context;
//外框大圆
cxt.lineWidth = this.B; //笔刷宽度
cxt.beginPath();
cxt.arc(0, 0, this.R - this.B, 0, 2 * Math.PI);
cxt.stroke();
cxt.closePath();
//填充黑色
cxt.fillStyle = "Black";
cxt.fill();
cxt.restore();
cxt.save();
//中心小圆
cxt.lineWidth = 3;
cxt.beginPath();
cxt.arc(0, 0, 3, 0, 2 * Math.PI);
cxt.stroke();
cxt.closePath();
//填充白色
cxt.fillStyle = "White";
cxt.fill();
cxt.restore();
cxt.save();
}
//画时针刻度
clock.prototype.drawHHScale = function () {
var cxt = this.context;
cxt.lineWidth = 3;
cxt.beginPath();
for (var i = 1; i < 13; i++) {
cxt.rotate(Math.PI / 6);
cxt.moveTo(this.R - this.B - 15, 0);
cxt.lineTo(this.R - this.B, 0);
}
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
}
//画分针刻度
clock.prototype.drawMMScale = function () {
var cxt = this.context;
cxt.lineWidth = 1;
cxt.beginPath();
for (var i = 0; i < 60; i++) {
if (i % 5 != 0) {
cxt.moveTo(this.R-this.B-8, 0);
cxt.lineTo(this.R-this.B, 0);
}
cxt.rotate(Math.PI / 30);
}
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
}
//画数字
clock.prototype.drawCCNumber = function () {
var cxt = this.context;
cxt.rotate(Math.PI / 2);
for (i = 0; i < 12; i++) {
var num = (i + 3 > 12) ? i + 3 - 12 : i + 3;
var numX = Math.round(Math.cos(i * Math.PI / 6) * (this.R - this.B - 30));
var numY = Math.round(Math.sin(i * Math.PI / 6) * (this.R - this.B - 30));
cxt.font = 'bold 12px 微软雅黑';
cxt.fillStyle = "White";
cxt.fillText(num, numX - 5, numY + 5);
}
cxt.restore();
cxt.save();
}
//画时针
clock.prototype.drawHHHand = function () {
var cxt = this.context;
cxt.rotate((Math.PI / 6) * this.HH + (Math.PI / 360) * this.MM + (Math.PI / 21600) * this.SS);
cxt.lineCap = "round";
cxt.beginPath();
cxt.moveTo(0, 0);
cxt.lineTo(this.R / 2, 0);
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
}
//画分针
clock.prototype.drawMMHand = function () {
var cxt = this.context;
cxt.rotate((Math.PI / 30) * this.MM + (Math.PI / 1800) * this.SS);
cxt.lineCap = "round";
cxt.beginPath();
cxt.moveTo(0, 0);
cxt.lineTo(this.R - this.B - 20, 0);
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
}
//画秒针
clock.prototype.drawSSHand = function () {
var cxt = this.context;
cxt.rotate(this.SS * Math.PI / 30);
cxt.lineWidth = 2;
cxt.beginPath();
cxt.moveTo(-20, 0);
cxt.lineTo(this.R - this.B - 5, 0);
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
}
//画品牌
clock.prototype.drawCCBrand = function () {
var cxt = this.context;
cxt.rotate(Math.PI / 2);
cxt.font = "15px Arial"
cxt.fillStyle = "White";
cxt.fillText(this.Brand, - 25, -(this.R - 80), 50);
cxt.restore();
cxt.save();
}
//还原画布到原始状态
clock.prototype.cxtBackOriginal = function () {
var cxt = this.context;
cxt.restore();
cxt.restore();
}
//主函数
function Main() {
var c = new clock("canvas");
//初始化
c.cxtInit();
//表盘
c.drawCCFace();
//刻度,数字
c.drawHHScale();
c.drawMMScale();
c.drawCCNumber();
//指针
c.drawHHHand();
c.drawMMHand();
c.drawSSHand();
//品牌
c.drawCCBrand();
//还原画布
c.cxtBackOriginal();
}
setInterval(Main, 1000);
</script>
</body>
</html>
复制代码
上面是初始版本,上面这个版本性能是极差的,因为每隔1秒就会创建1个新对象,即:new clock()
刚开始想到的解决方案是用 单例模式 ,但结果行不通,因为时间必须是实时的,如果用 单例模式 则时间就一直是第一次new clock()时的那个时间,因此也就不会走针。
之后修改如下:
复制代码
<html>
<head>
<title>Html5 canvas 钟表</title>
<style type="text/css">
canvas{ border:2px solid Gray; background-color:Gray;}
</style>
</head>
<body>
<canvas></canvas>
<script type="text/javascript">
//时钟对象
function clock(canvasID) {
//取得画布对象
var canvas = document.getElementById(canvasID);
this.context = canvas.getContext("2d");
//宽,高,半径,表盘外边框宽度,品牌文字
this.W = canvas.offsetWidth;
this.H = canvas.offsetHeight;
this.R = this.W / 2;
this.B = 12;
this.Brand = "SIMILAR";
}
//初始化设置
clock.prototype.cxtInit = function () {
var cxt = this.context;
cxt.save(); //保存画布原始状态
cxt.clearRect(0, 0, this.W, this.H); //清空画布
cxt.lineWidth = 3; //笔刷宽度为3
cxt.strokeStyle = "White"; //笔刷颜色为白色
cxt.translate(this.R, this.R); //定位中心点
cxt.rotate(-Math.PI / 2); //旋转负90度
cxt.save(); //保存初始化设置后的状态
}
//画表盘
clock.prototype.drawCCFace = function () {
var cxt = this.context;
//外框大圆
cxt.lineWidth = this.B; //笔刷宽度
cxt.beginPath();
cxt.arc(0, 0, this.R - this.B, 0, 2 * Math.PI);
cxt.stroke();
cxt.closePath();
//填充黑色
cxt.fillStyle = "Black";
cxt.fill();
cxt.restore();
cxt.save();
//中心小圆
cxt.lineWidth = 3;
cxt.beginPath();
cxt.arc(0, 0, 3, 0, 2 * Math.PI);
cxt.stroke();
cxt.closePath();
//填充白色
cxt.fillStyle = "White";
cxt.fill();
cxt.restore();
cxt.save();
}
//画时针刻度
clock.prototype.drawHHScale = function () {
var cxt = this.context;
cxt.lineWidth = 3;
cxt.beginPath();
for (var i = 1; i < 13; i++) {
cxt.rotate(Math.PI / 6);
cxt.moveTo(this.R - this.B - 15, 0);
cxt.lineTo(this.R - this.B, 0);
}
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
}
//画分针刻度
clock.prototype.drawMMScale = function () {
var cxt = this.context;
cxt.lineWidth = 1;
cxt.beginPath();
for (var i = 0; i < 60; i++) {
if (i % 5 != 0) {
cxt.moveTo(this.R-this.B-8, 0);
cxt.lineTo(this.R-this.B, 0);
}
cxt.rotate(Math.PI / 30);
}
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
}
//画数字
clock.prototype.drawCCNumber = function () {
var cxt = this.context;
cxt.rotate(Math.PI / 2);
for (i = 0; i < 12; i++) {
var num = (i + 3 > 12) ? i + 3 - 12 : i + 3;
var numX = Math.round(Math.cos(i * Math.PI / 6) * (this.R - this.B - 30));
var numY = Math.round(Math.sin(i * Math.PI / 6) * (this.R - this.B - 30));
cxt.font = 'bold 12px 微软雅黑';
cxt.fillStyle = "White";
cxt.fillText(num, numX - 5, numY + 5);
}
cxt.restore();
cxt.save();
}
//画指针
clock.prototype.drawCCHand = function () {
var tt = new Date();
//时,分,秒
var hh = tt.getHours() > 12 ? tt.getHours() - 12 : tt.getHours();var mm = tt.getMinutes();
var ss = tt.getSeconds();
var cxt = this.context;
//画时针
cxt.rotate((Math.PI / 6) * hh + (Math.PI / 360) * mm + (Math.PI / 21600) * ss);
cxt.lineCap = "round";
cxt.beginPath();
cxt.moveTo(0, 0);
cxt.lineTo(this.R / 2, 0);
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
//画分针
cxt.rotate((Math.PI / 30) * mm + (Math.PI / 1800) * ss);
cxt.lineCap = "round";
cxt.beginPath();
cxt.moveTo(0, 0);
cxt.lineTo(this.R - this.B - 20, 0);
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
//画秒针
cxt.rotate(ss * Math.PI / 30);
cxt.lineWidth = 2;
cxt.beginPath();
cxt.moveTo(-20, 0);
cxt.lineTo(this.R - this.B - 5, 0);
cxt.stroke();
cxt.closePath();
cxt.restore();
cxt.save();
}
//画品牌
clock.prototype.drawCCBrand = function () {
var cxt = this.context;
cxt.rotate(Math.PI / 2);
cxt.font = "15px Arial"
cxt.fillStyle = "White";
cxt.fillText(this.Brand, - 25, -(this.R - 80), 50);
cxt.restore();
cxt.save();
}
//还原画布到原始状态
clock.prototype.cxtBackOriginal = function () {
var cxt = this.context;
cxt.restore();
cxt.restore();
}
//主函数
function Main() {
var c = new clock("canvas");
setInterval(function () {
//初始化
c.cxtInit();
//表盘
c.drawCCFace();
//刻度,数字
c.drawHHScale();
c.drawMMScale();
c.drawCCNumber();
//指针
c.drawCCHand();
//品牌
c.drawCCBrand();
//还原画布到原始状态
c.cxtBackOriginal();
}, 1000);
}
Main();
</script>
</body>
</html>
复制代码
修改的地方:
1.>将画指针的3个方法(即,画时针,分针,秒针)合并成了一个方法( 即,画指针 drawCCHand() )
2.>将时间的获取放到了drawCCHand()方法里面,而不是在构造函数里面。
3.>在初始化方法cxtInit()里面加了一句代码:cxt.clearRect(0, 0, this.W, this.H); //清空画布。因为不会重新创建clock对象,所以每次画前要清空前一秒的画布内容