原生js之canvas时钟组件

canvas一直是前端开发中不可或缺的一种用来绘制图形的标签元素,比如压缩上传的图片、比如刮刮卡、比如制作海报、图表插件等,很多人在面试的过程中也会被问到有没有接触过canvas图形绘制。
定义
canvas元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成。
canvas标签只是图形容器,您必须使用脚本来绘制图形。

浏览器支持
Internet Explorer 9、Firefox、Opera、Chrome 和 Safari 支持

那么本篇文章就通过一个时钟组件来熟悉使用一下关于canvas的api。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>canvas时钟</title>
<style>
*{margin:0;padding:0;}
body{text-align:center;padding-top:100px;}
</style>
</head>
<body>
<canvas id="clock" width="200px" height="200px"></canvas>
<script>
(function(win){
    function DrawClock(options){
        this.canvas = options.el;
        this.ctx    = this.canvas.getContext('2d');//方法返回一个用于在画布上绘图的环境
        this.width  = this.ctx.canvas.width;
        this.height = this.ctx.canvas.height;
        this.r      = this.width / 2;
        this.rem    = this.width / 200;
        this.digits = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];

        var self    = this;
        self.init();
        setInterval(function(){
            self.init();
        }, 1000);
    }

    DrawClock.prototype = {
        init: function(){
            var ctx = this.ctx;
            ctx.clearRect(0, 0, this.width, this.height);    //在给定的矩形内清除指定的像素
            var now = new Date();
            var hours = now.getHours();
            var minutes = now.getMinutes();
            var seconds = now.getSeconds();

            var hour = hours >= 12 ? hours - 12 : hours;
            var minute = minutes + seconds / 60;

            this.drawBackground();
            this.drawHour(hour, minute);
            this.drawMinute(minute);
            this.drawSecond(seconds);
            this.drawDot();
            ctx.restore();
        },
        drawBackground: function(){
            var ctx = this.ctx;
            var self = this;
            ctx.save();
            ctx.translate(this.r, this.r);         //重新映射画布上的 (0,0) 位置
            ctx.beginPath();
            ctx.lineWidth = 8 * this.rem;
            ctx.arc(0, 0, this.r - ctx.lineWidth / 2, 0, 2 * Math.PI, false);    //创建弧/曲线(用于创建圆形或部分圆)
            ctx.stroke();
            ctx.font = 16  * this.rem + "px Arial";//设置或返回文本内容的当前字体属性
            ctx.textAlign = "center";              //设置或返回文本内容的当前对齐方式
            ctx.textBaseline = "middle";           //设置或返回在绘制文本时使用的当前文本基线
            this.digits.forEach(function(number, i){
                var rad = 2 * Math.PI / 12 * i;
                var x = Math.cos(rad) * (self.r - 33 * self.rem);
                var y = Math.sin(rad) * (self.r - 33 * self.rem);
                ctx.fillText(number, x, y);        //在画布上绘制"被填充的"文本
            });

            //分钟的刻度,每分钟转6deg
            for (var i = 0; i < 60; i++){
                ctx.save();                        //保存当前环境的状态
                ctx.rotate(6 * i * Math.PI / 180); //旋转当前绘图
                ctx.beginPath();                   //起始一条路径,或重置当前路径
                ctx.moveTo(0, -82 * this.rem);     //把路径移动到画布中的指定点,不创建线条
                ctx.lineTo(0, -87 * this.rem);     //添加一个新点,然后在画布中创建从该点到最后指定点的线条
                ctx.closePath();                   //创建从当前点回到起始点的路径
                ctx.strokeStyle = '#000';          //设置或返回用于笔触的颜色、渐变或模式
                ctx.lineWidth = 1 * this.rem;      //设置或返回当前的线条宽度
                ctx.stroke();                      //绘制已定义的路径
                ctx.restore();                     //返回之前保存过的路径状态和属性
            }
            //小时的刻度,每小时转30deg
            for (var i = 0; i < 12; i++){
                ctx.save();
                ctx.rotate(30 * i * Math.PI / 180);
                ctx.beginPath();
                ctx.moveTo(0, -79 * this.rem);
                ctx.lineTo(0, -87 * this.rem);
                ctx.closePath();
                ctx.strokeStyle = '#000';
                ctx.lineWidth = 2 * this.rem;
                ctx.stroke();
                ctx.restore();
            }
        },
        drawHour: function(hour, minute){
            var ctx = this.ctx;
            ctx.save();
            ctx.beginPath();
            var hRad = 2 * Math.PI / 12 * hour;
            var mRad = 2 * Math.PI / 12 / 60 * minute;
            ctx.rotate(hRad + mRad);
            ctx.lineWidth = 6 * this.rem;
            ctx.lineCap = "round";                 //设置或返回线条的结束端点样式
            ctx.moveTo(0, 10 * this.rem);
            ctx.lineTo(0, -this.r / 2);
            ctx.stroke();
            ctx.restore();
        },
        drawMinute: function(minute){
            var ctx = this.ctx;
            ctx.save();
            ctx.beginPath();
            var rad = 2 * Math.PI / 60 * minute;
            ctx.rotate(rad);
            ctx.lineWidth = 3 * this.rem;
            ctx.lineCap = "round";
            ctx.moveTo(0, 10 * this.rem);
            ctx.lineTo(0, -this.r + 26 * this.rem);
            ctx.stroke();
            ctx.restore();
        },
        drawSecond: function(second){
            var ctx = this.ctx;
            ctx.save();
            ctx.beginPath();
            ctx.fillStyle = "#c14543";
            var rad = 2 * Math.PI / 60 * second;
            ctx.rotate(rad);
            ctx.moveTo(-3 * this.rem, 20 * this.rem);
            ctx.lineTo(3 * this.rem, 20 * this.rem);
            ctx.lineTo(1, -this.r + 26 * this.rem);
            ctx.lineTo(-1, -this.r + 26 * this.rem);
            ctx.fill();    //填充当前绘图(路径)
            ctx.restore();
        },
        drawDot: function(minute){
            var ctx = this.ctx;
            ctx.beginPath();
            ctx.fillStyle = "#fff";
            ctx.arc(0, 0, 3 * this.rem, 0, 2 * Math.PI, false);
            ctx.fill();
        }
    };

       win.DrawClock = DrawClock;
})(window);

new DrawClock({el: document.getElementById("clock")});
</script>
</body>
</html>

只要心中有丘壑,就能耕出二亩田!canvas时钟用到了canvas中大部分的api,通过学习canvas时钟的代码实现,很能了解canvas的属性和方法,同时,实现时钟效果时,用到了数学中的几何模型正弦sin和余弦cos以及弧度的计算方法,又重温了一把当年学数学时的许多乐趣,可谓是一举两得。

时钟效果图如下:

原文地址:https://www.cnblogs.com/tnnyang/p/8951804.html

时间: 2024-11-10 11:19:14

原生js之canvas时钟组件的相关文章

原生JS的&lt;canvas&gt;标签画时钟

首先要申明本人对于美除了美女真没什么要求. 其次讲讲次学习碰到重要知识点: 1.画圆(弧): context.arc(x, y, radius, Math.PI / 180 * startAngle, Math.PI / 180 * endAngle, anticlockwise); x:横坐标: y:纵坐标: radius:半径: startAngle:Math.PI / 180 这个在数学上表示1度,这边需要用圆弧表示,所以需要多少就写多少.表示弧线开始的角度. endAngle:同理,表示

原生js实现中文时钟

零.寒暄 终于一个月可以更新两篇博客了,开心.昨天花了大概一天的时间玩了下github,基本的clone和push都搞定了,如果有和我一样的新手没调通的,大家可以交流. 另外,说个题外话,大家发现我的博客右上角多了一个“Fork me  on GitHub”,瞬间B格提升了许多,哈哈.咋搞的,其实很简单,简要的说下: (1)进入github官方博客,链接在这里,手动链接:https://github.com/blog/273-github-ribbons,选择一个你喜欢的样式,比如我这个: 大家

Java学习总计(二十六)——JavaScript正则表达式,Js表单验证,原生js+css页面时钟

一.JavaScript正则表达式1.exec检索字符串中指定的值,返回找到的值,并确定其位置2.test检索字符串中指定的值,返回true或false3.正则表达式对象的创建:(1)方式一:Var rgex=new RegExp("[0-9]","模式");(2)方式二:简便写法,用双斜杠//把正则表达式的内容括起来例1(正则创建,使用test()方法): <!DOCTYPE html> <html> <head> <me

原生JS实现动态时钟(优化)

<!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title> </head> <body> <p id="num"></p> <a href="javascript:stop()">让时间停止吧</a> <a hr

原生js拼图,封装,组件化

利用原生js实现拼图游戏,实现封装,变为插件,组件化,传入参数调用, 使用立即执行函数,将变量私有化,不污染全局, 利用canvas展示效果,减少dom操作,不影响HTML结构: 1 var myPingTu = (function(){ 2 function init(row_i,dom){ 3 var myCanvas = dom; 4 var row = row_i || 3,// 行列数 5 arr = [], 6 num = row * row;// 块个数 7 if (!myCanv

用.native修饰器来对外部组件进行构造器内部方法的调用以及用原生js获取构造器里的方法

html <div id="app"> <span v-text="number"></span> <btn @click.native="add(10,$event)"></btn> <button @click="add(10,$event)">add</button> </div> <button onclick=&qu

原生js canvas 碰撞游戏的开发笔记

-----------------------------------------------福利--------------------------------------------- -----------------------------------------------分割线--------------------------------------------- 今天 我们研究下碰撞游戏 什么是碰撞游戏? 当然是东西碰到在一起啦 用前端逻辑来说 就是2个物品互相碰撞产生的事件 问

原生js实现的3个小特效(时钟、轮播图、选项卡)

时钟: <p id="timeTxt"></p>  //将获取到的时间显示在timeTxt这里面        <button onclick="startTime()">关闭</button>        <!--时钟-->        function startTime(){  //创建startTime()函数            var today=new Date();  //定义一个对象

原生JS面向对象思想封装轮播图组件

原生JS面向对象思想封装轮播图组件 在前端页面开发过程中,页面中的轮播图特效很常见,因此我就想封装一个自己的原生JS的轮播图组件.有了这个需求就开始着手准备了,代码当然是以简洁为目标,轮播图的各个功能实现都分别分为不同的模块.目前我封装的这个版本还不适配移动端,只适配PC端. 主要的功能有:自动轮播,点击某一张图片对应的小圆点就跳转到指定图片,有前后切换按钮.使用的时候只需要传入图片的路径以及每张图片分别所对应的跳转路径还有目标盒子ID就可以了,还可以自定义每张图轮播的延时,不过延时参数不是必须