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

时间: 2024-10-25 18:53:21

Html5 canvas 钟表的相关文章

HTML5 Canvas 画钟表

画钟表是2D画图的老生常谈,我也不能免俗弄了一个.代码如下: <!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <head> <title>钟表</title> </head> <body onloa

HTML5 Canvas 绘制二十四字真言钟表

代码: <!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <head> <title>钟表</title> </head> <body > <canvas id="myCanvu

html5 canvas 详细使用教程

导航 前言 基本知识 绘制矩形 清除矩形区域 圆弧 路径 绘制线段 绘制贝塞尔曲线 线性渐变 径向渐变(发散) 图形变形(平移.旋转.缩放) 矩阵变换(图形变形的机制) 图形组合 给图形绘制阴影 绘制图像(图片平铺.裁剪.像素处理[不只图像.包括其他绘制图形]) 绘制文字 保存和恢复状态(context) 保存文件 结合setInterval制作动画 结语.demo下载   前言 <canvas></canvas>是html5出现的新标签,像所有的dom对象一样它有自己本身的属性.

html5 Canvas绘制图形入门详解

html5,这个应该就不需要多作介绍了,只要是开发人员应该都不会陌生.html5是「新兴」的网页技术标准,目前,除IE8及其以下版本的IE浏览器之外,几乎所有主流浏览器(FireFox.Chrome.Opera.Safari.IE9+)都已经开始支持html5了.除此之外,在移动浏览器市场上,众多的移动浏览器也纷纷展开关于「html5的支持能力以及性能表现」的军备竞赛.html作为革命性的网页技术标准,再加上众多浏览器厂商或组织的鼎力支持,可以想见,html5将会成为未来网页技术的领头羊. ht

html5 canvas首屏自适应背景动画循环效果代码

模板描述:html5 canvas首屏自适应背景动画循环效果代码 由于动态图太大,怕以后服务器受不了,所以现在都改为静态图了,大家点击演示地址一样的,希望大家喜欢,你们的支持就是小海的动力!! 欢迎大家积极评论,给出宝贵意见 下 载 演示地址 本文地址:html5 canvas首屏自适应背景动画循环效果代码

前端-HTML5 canvas学习

canvas元素算是HTML5添加的最受欢迎的功能了.它是通过在页面中设定一个区域,然后用脚本来编辑图形. 可像下面这样来引入一个canvas图像 <canvas id="myCanvas"></canvas> <script type="text/javascript"> var canvas = document.getElementById('myCanvas'); var cxt = canvas.getContext('

html5 canvas文本处理

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

如何使用 HTML5 Canvas 制作水波纹效果

原文:如何使用 HTML5 Canvas 制作水波纹效果 今天,我们继续分享 JavaScript 实现的效果例子,这篇文章会介绍使用 JavaScript 实现水波纹效果.水波效果以图片为背景,点击图片任意位置都会触发.有时候,我们使用普通的 Javascript 就可以创建一个很有趣的解决功能. 在线演示      源码下载 Step 1. HTML 和以前一样,首先是 HTML 代码: <!DOCTYPE html> <html> <head> <meta

HTML5 画布上的 Three.js 环境灯光(HTML5 Canvas Three.js Ambient Lighting)

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. HTML5 画布上的 Three.js 环境灯光HTML5 Canvas Three.js Ambient Lighting <!DOCTY