首页 > 代码库 > Html5 canvas 钟表

Html5 canvas 钟表

原文:Html5 canvas 钟表

看到有不少人用canvas写钟表,今天也来加入他们,自己实现个。

 

效果图:

 

实现代码如下:

<html><head>    <title>Html5 canvas 钟表</title>    <style type="text/css">        canvas{ border:2px solid Gray; background-color:Gray;}    </style></head><body>    <canvas width="250" height="250"  id="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 width="250" height="250"  id="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对象,所以每次画前要清空前一秒的画布内容

 

如果大家还有好的优化方案或建议,就分享下吧。

推广个新建的WEB前端QQ群:142512178

Html5 canvas 钟表