Html5 canvas 钟表

简介: 原文:Html5 canvas 钟表看到有不少人用canvas写钟表,今天也来加入他们,自己实现个。   效果图:   实现代码如下: Html5 canvas 钟表 canvas{ border:2px solid Gray; ba...
原文: 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

目录
相关文章
|
移动开发 前端开发 API
HTML5 Canvas 填充与描边(Fill And Stroke)
HTML5 Canvas 填充与描边(Fill And Stroke)
341 3
|
移动开发 前端开发 JavaScript
基于 HTML5 和 Canvas 开发的在线图片编辑器
基于 HTML5 和 Canvas 开发的在线图片编辑器
754 0
|
移动开发 前端开发 HTML5
基于HTML5+Canvas绘制的鼠标跟随三角形碎片光标动画代码
基于HTML5+Canvas绘制的鼠标跟随三角形碎片光标动画特效代码,很有意思,一团三角形碎片跟随鼠标的移动,不冗长、不笨重,反而有一种很轻盈的感觉,非常不错
290 29
|
移动开发 前端开发 HTML5
Html5 Canvas绘制圆形仪表盘动画源码
Html5 Canvas绘制圆形仪表盘动画特效是一款基于HTML5 Canvas绘制的圆形百分比仪表盘动画特效。
275 1
|
Web App开发 移动开发 前端开发
html5 canvas五彩碎纸屑飘落动画特效
h5 canvas飘落纸片动画是一款实现五彩纸屑飘落的背景动画特效,基于canvas绘制的空中飘落的纸屑片动画特效,适用于网页动态背景效果代码。简单使用,欢迎下载!代码适用浏览器:搜狗、360、FireFox(建议)、Chrome、Safari、Opera、傲游、世界之窗,是一款不错的的特效插件,希望大家喜欢!
313 5
|
前端开发
基于canvas实现的彩色纸屑组成文字3d动画HTML源码
基于canvas实现的彩色纸屑组成文字3d动画HTML源码
216 0
基于canvas实现的彩色纸屑组成文字3d动画HTML源码
|
移动开发 前端开发 HTML5
HTML5 Canvas制作的粒子十秒倒计时源码
一段基于HTML5 Canvas制作的粒子爆炸,十秒数字倒计时,全屏倒计时动画效果,给人一种非常大气的视觉感
267 0
HTML5 Canvas制作的粒子十秒倒计时源码
|
前端开发 JavaScript
Canvas三维变化背景动画HTML源码
Canvas三维变化背景动画HTML源码
257 5
|
XML 移动开发 前端开发
HTML5 SVG和canvas的性能探讨
HTML5 中的 SVG(可缩放矢量图形)和 Canvas(画布)分别用于网页图形绘制。SVG 基于矢量图形,使用 XML 描述,适合静态或少量动态内容(如图标、图表),易于编辑且保持高分辨率;Canvas 则基于位图,通过 JavaScript 绘制,更适合快速更新大量图形的场景(如游戏、动态动画),但在复杂图形计算时可能遇到性能瓶颈。总体而言,SVG 适用于静态和少量动态内容,而 Canvas 更适合高频率更新和性能要求高的场景。
|
移动开发 前端开发 JavaScript
HTML5 Canvas详解及应用
HTML5 Canvas 允许通过 JavaScript 在网页上动态绘制图形、动画等视觉内容。首先在 HTML 中定义 `&lt;canvas&gt;` 元素,并通过 JavaScript 获取画布上下文进行绘制。常见方法包括绘制矩形、路径、圆形和文本,以及处理图像和创建动画效果。适用于游戏开发、数据可视化、图像编辑和动态图形展示等多种应用场景。需要注意性能优化、无状态绘制及自行处理事件等问题。