通过Canvas + JS 实现简易时钟实战

简介: 最近通过各种渠道学习了下html5中的canvas元素,为了练练手就随手写了一个简易的时钟。时钟本身不复杂,没有使用图片进行美化,下面就与大家分享一下具体的代码:     这是最终实现的效果: 部分的启发点来自于 http://developer.

最近通过各种渠道学习了下html5中的canvas元素,为了练练手就随手写了一个简易的时钟。时钟本身不复杂,没有使用图片进行美化,下面就与大家分享一下具体的代码:


 

 

这是最终实现的效果:

部分的启发点来自于 http://developer.51cto.com/art/201503/467645.htm

 

html代码:

 <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Clock</title>
        <style type="text/css">
        *{
            margin: 0;
            padding: 0;
        }
        .canvas{
            margin-left: 20px;
            margin-top: 20px;
           
            
        }
        </style>
    </head>
    <body onload="main()">
     <canvas class = "canvas" id="canvasId" width = '400' height = '400'></canvas>

  </body>

js代码:

    var Clockbox = function(obj,width,height){
            this.o = {
                'dates':[],                        //时间
                'obj':obj,                            //canvas对象
                'width':width,                        //canvas宽度
                'height':height,                    //canvas高度
                'obj2d':obj.getContext('2d'),        //2d对象
                'wcolor':'#000000',                    //线条颜色
                'scalewidth':30,                     //刻度长度
                'msradius':(1/30)*Math.PI,            //分秒的弧度
                'hsradius':(1/6)*Math.PI,            //时的弧度
                 'hourHandLength' : (width/5),         /*时针长度*/
                'minHandLength':(width/6*1.8),         /*分针长度*/
                'secHandLength':(width/20*8),         /*秒针长度*/
                'fontsize':30                       //数字大小
            }
            var _this = this;
            this.infn();
            setInterval(function(){
              _this.o.obj2d.translate(-_this.o.width/2,-_this.o.height/2);
                _this.o.obj2d.clearRect(0,0,_this.o.width,_this.o.height);

                _this.infn();
            },1000)
        }
        Clockbox.prototype = {
            infn:function(){
                //表盘
                var obj2d = this.o.obj2d;
               
                var dates = new Date();
                this.o.dates = [dates.getHours(),dates.getMinutes(),dates.getSeconds()];
            
                //绘制
                obj2d.beginPath();
                obj2d.arc(this.o.width/2,this.o.height/2,this.o.width/2,0,2*Math.PI,false);
                obj2d.strokeStyle = this.o.wcolor;
                obj2d.stroke();
                
                //刻度
                this.scalefn(obj2d);
                //时针
                this.hour(obj2d);
                //分针
                this.minute(obj2d);
                //秒针
                this.sec(obj2d);
            },
            //绘制刻度和指针
            scalefn:function(obj2d){
                obj2d.translate(this.o.width/2,this.o.height/2);
                for(var i = 0;i<12;i++){
                    obj2d.moveTo(this.o.width/2-this.o.scalewidth, 0);
                       obj2d.lineTo(this.o.width/2, 0);  
                    obj2d.rotate(this.o.hsradius);
                }
                obj2d.font = "bold "+this.o.fontsize+"px impack";
                obj2d.textAlign = "center";
                obj2d.fillStyle = "#ff9000";
                obj2d.fillText("12",0,-((this.o.width/2)-(this.o.scalewidth*2+10)));
                obj2d.fillText("3",((this.o.width/2)-(this.o.scalewidth*2)),this.o.fontsize/3);
                obj2d.fillText("6",0,((this.o.width/2)-(this.o.scalewidth*2)));
                obj2d.fillText("9",-((this.o.width/2)-(this.o.scalewidth*2)),this.o.fontsize/3);
                obj2d.stroke();
                obj2d.restore();
            },
            //时针
            hour:function(obj2d){
                  obj2d.save();
                  obj2d.rotate(this.o.hsradius*Number(this.o.dates[0]));
                
                obj2d.moveTo(0,0);
                obj2d.lineTo(0,-this.o.hourHandLength);
                
                obj2d.stroke();
                obj2d.restore();
            },
            //分针
            minute:function(obj2d){
                obj2d.save();
                obj2d.rotate(this.o.msradius*Number(this.o.dates[1]));
                 obj2d.beginPath();
                obj2d.moveTo(0,0);
                obj2d.lineTo(0,-this.o.minHandLength);
                
                obj2d.stroke();
                obj2d.restore();
            },
            //秒针
            sec:function(obj2d){
                obj2d.save();
                obj2d.rotate(this.o.msradius*Number(this.o.dates[2]));
                obj2d.beginPath();
                obj2d.moveTo(0,0);
                obj2d.lineTo(0,-this.o.secHandLength);
                
                obj2d.stroke();
                obj2d.restore();
            }
        }
       function main(){

     var can = document.getElementById('canvasId');
            var Clock =    new Clockbox(can,400,400);
        
      }

js代码详解:

      1.首先这里使用了面向对象的形式

      2.这里为了方便更改大小,传入了3个参数 obj,width,height,分别表示canvas元素  以及它的宽度和高度,表盘的半径是宽的二分之一  

      3. 因为1小时有60分钟  所以每一个分钟单元格应该有的弧度就是(1/(60/2))*Math.PI,小时同理

      4.   依据现在的时间 用 .rotate()方法对指针做角度控制 12点的时针的弧度就是 一个小时的弧度*12

      5.最后每秒不断的清除画布  重构 就形成了一个动态的时钟

 

 

遇到的问题:

 

   translate()  在画完之后 canvas的原点并不在左上角了   ..... 最后在定时器重新设定解决了这个问题 

 

======================================================== 转载请注明出处。
目录
相关文章
|
12月前
|
人工智能 自然语言处理 JavaScript
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
575 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
|
8月前
|
JavaScript 前端开发 安全
【逆向】Python 调用 JS 代码实战:使用 pyexecjs 与 Node.js 无缝衔接
本文介绍了如何使用 Python 的轻量级库 `pyexecjs` 调用 JavaScript 代码,并结合 Node.js 实现完整的执行流程。内容涵盖环境搭建、基本使用、常见问题解决方案及爬虫逆向分析中的实战技巧,帮助开发者在 Python 中高效处理 JS 逻辑。
|
10月前
|
JavaScript 前端开发 算法
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
256 1
|
自然语言处理 JavaScript 前端开发
深入理解JavaScript中的闭包:原理与实战
【10月更文挑战第12天】深入理解JavaScript中的闭包:原理与实战
html+js+css实现的建筑方块立体数字时钟源码
html+js+css实现的建筑方块立体数字时钟源码
629 33
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
一个好看的小时钟html+js+css源码
一个好看的小时钟html+js+css源码
278 24
Next.js 实战 (二):搭建 Layouts 基础排版布局
本文介绍了作者在Next.js v15.x版本发布后,对一个旧项目的重构过程。文章详细说明了项目开发规范配置、UI组件库选择(最终选择了Ant-Design)、以及使用Ant Design的Layout组件实现中后台布局的方法。文末展示了布局的初步效果,并提供了GitHub仓库链接供读者参考学习。
524 1
Next.js 实战 (二):搭建 Layouts 基础排版布局
|
监控 安全 中间件
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
这篇文章介绍了什么是Next.js中的中间件以及其应用场景。中间件可以用于处理每个传入请求,比如实现日志记录、身份验证、重定向、CORS配置等功能。文章还提供了一个身份验证中间件的示例代码,以及如何使用限流中间件来限制同一IP地址的请求次数。中间件相当于一个构建模块,能够简化HTTP请求的预处理和后处理,提高代码的可维护性,有助于创建快速、安全和用户友好的Web体验。
418 0
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
|
中间件 API
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?
这篇文章介绍了作者在使用Nextjs15进行项目开发时遇到的部署问题。在部署过程中,作者遇到了打包构建时的一系列报错,报错内容涉及动态代码评估在Edge运行时不被允许等问题。经过一天的尝试和调整,作者最终删除了lodash-es库,并将radash的部分源码复制到本地,解决了打包报错的问题。文章最后提供了项目的线上预览地址,并欢迎读者留言讨论更好的解决方案。
418 0
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?

热门文章

最新文章