canvas时钟

    xiaoxiao2022-07-03  125

    canvas是HTML5新增的组件,提供了新的javascript API。它最初由苹果内部使用自己MacOS X WebKit推出,供应用程序使用像仪表盘的构件和 Safari 浏览器使用。后来,有人通过Gecko内核的浏览器 (尤其是Mozilla和Firefox),Opera和Chrome和超文本网络应用技术工作组建议为下一代的网络技术使用该元素。canvas就像是页面上的一块画布,而javascript是一支笔,可以在画布上绘制多种多样的图形,丰富了前端开发方式,为前段的发展注入了新的活力。canvas默认宽高是300px * 150px,且必须在行内设置宽高。步入正题:

     

    最近几天研究了下如何用canvas绘制时钟,github地址:https://github.com/lishuai336/canvasClock

    首先创建画布:Mozilla 程序从 Gecko 1.8 (Firefox 1.5)开始支持 <canvas>, Internet Explorer 从IE9开始<canvas> 。Chrome和Opera 9+ 也支持 ,canvas标签的内容在不支持canvas的浏览器才会显示。

    <div> <canvas id="clock" width="300" height="300">您的浏览器不支持canvas,请升级浏览器 </canvas> </div>

    1.  getContext("2d")获得2d上下文

    canvas本身并没有提供太多的API,绘图的各种API主要来自getContext对象。"2d", 是建立一个 CanvasRenderingContext2D 二维渲染上下文。在未来,如果 canvas 标签扩展到支持 3D 绘图,getContext() 方法可能允许传递一个 "3d" 字符串参数。不过越来越多的浏览器开始支持webGL,也就是浏览器端的3D标准,它直接借助系统显卡来渲染 3D 场景,所以getContext(“3d”)的时代很可能不会出现。不过,利用透视现象可以用getContext(“2d”)绘制出3D的视觉效果,emmm,这个有点厉害。 

     

    var canvasClock = document.getElementById("clock"); var canvasContext = canvasClock.getContext("2d"); //getContext返回一个对象,该对象提供了用于在画布上绘图的方法和属性 var canvasWidth = canvasContext.canvas.width; var canvasHeight = canvasContext.canvas.height; var radius = canvasWidth / 2; //圆的半径

    2. 绘制时钟的外围圆形

    translate(x,y)设置画布的原点,也就是画画起笔的位置,lineWidth线条宽度,arc(x,y,r,sAngle,eAngle,counterclockwise),绘制圆形,里面几个参数分别代表:圆心坐标,圆半径,起始角(以弧度计,弧的圆形的三点钟位置是 0 度),结束角,顺时针还是逆时针。stroke()绘制定义的路径。

    canvasContext.translate(radius, radius); //移动画布原点到中心点 canvasContext.beginPath(); //beginPath 开始一条路径,或者重置一条路径 canvasContext.lineWidth = 8; //线条宽度 canvasContext.arc(0, 0, radius - canvasContext.lineWidth / 2, 0, 2*Math.PI, false); //创建圆形路径s canvasContext.stroke(); //绘制已定义的路径

     3.  绘制12个数字

    1个小时的弧度是2π / 12 ,起始角是在3点处,所以数组第一个数从3开始。知道圆的半径,和每个点的弧度数,就可以通过sin和cos计算出每个数字的坐标。textAlign文字水平对齐方式,textBaseline设置文字基线(可以理解为文字垂直对齐方式)。

    var hourNumber = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2]; canvasContext.font = 18 + "px Microsoft YaHei"; //设置文本大小 canvasContext.textAlign = "center"; //设置文本水平对其方式 canvasContext.textBaseline = "middle"; //设置文本垂直对齐方式 hourNumber.forEach(function(number, i){ var radian = 2 * Math.PI / 12 * i; //每个小时的弧度 var radianX = (radius - 30) * Math.cos(radian); //每个小时X坐标 var radianY = (radius - 30) * Math.sin(radian); //每个小时Y坐标 canvasContext.fillText(number, radianX, radianY); //绘制“被填充的”文本 });

     4.  绘制60个刻度

     这和绘制12个数字一样,不过每个刻度的弧度是2π / 60,12个时刻点的颜色做个区分。fillStyle填充绘画的颜色。

    for(var i = 0; i < 60; i++){ var radian = 2 * Math.PI / 60 * i; var x = (radius - 16) * Math.cos(radian); var y = (radius - 16) * Math.sin(radian); canvasContext.beginPath(); if(i % 5 == 0){ canvasContext.fillStyle = "#000"; } else{ canvasContext.fillStyle = "#ccc"; } canvasContext.arc(x, y, 2, 0, 2 * Math.PI, false); canvasContext.fill(); }

     5.  绘制时针

     时针运动时的旋转角度=当前时间的小时数+分针数+秒针数。由于时钟每秒变动一次,实则每一秒都要重新绘制一次画布内容。所以每次在执行之前都要保存下最开始的画布环境save();绘制完成后还原画布环境restore()。

    function drawHour(hour, minutes, seconds){ canvasContext.save(); //保存绘画前的画布环境 canvasContext.beginPath(); var radianHour = 2 * Math.PI / 12 * hour; var radianMinutes = 2 * Math.PI / 12 / 60 * minutes var radianSeconds = 2 * Math.PI / 12 / 60 / 60 * seconds; canvasContext.rotate(radianHour + radianMinutes + radianSeconds); canvasContext.lineWidth = 6 * rem; canvasContext.lineCap = "round"; canvasContext.moveTo(0, 10 * rem); canvasContext.lineTo(0, -radius / 2); canvasContext.stroke(); canvasContext.restore(); //还原初始画布环境 }

      6.  绘制分针

     分针同理,rotate()画布旋转角度。

    function drawMinute(minutes, seconds){ canvasContext.save(); canvasContext.beginPath(); var radianMinutes = 2 * Math.PI / 60 * minutes; var radianSeconds = 2 * Math.PI / 60 / 60 * seconds; canvasContext.rotate(radianMinutes + radianSeconds); canvasContext.lineWidth = 4 * rem; canvasContext.lineCap = "round"; canvasContext.moveTo(0, 12 * rem); canvasContext.lineTo(0, -radius + 30 * rem); canvasContext.stroke(); canvasContext.restore(); }

      7.  绘制秒针

    秒针绘制成头尖尾宽的红色梯形。 

    function drawSeconds(seconds){ canvasContext.save(); canvasContext.beginPath(); canvasContext.fillStyle = "#c14543"; var radian = 2 * Math.PI / 60 * seconds; canvasContext.rotate(radian); canvasContext.moveTo(2 * rem, 20 * rem); canvasContext.lineTo(-2 * rem, 20 * rem); canvasContext.lineTo(-1 * rem, -radius + 18 * rem); canvasContext.lineTo(1 * rem, -radius + 18 * rem); canvasContext.fill(); canvasContext.restore(); }

    8.  仿螺丝

    在时针中心绘制一个白点,用于模仿固定钟表指针的螺丝。 

    function drawDot(){ canvasContext.save(); canvasContext.beginPath(); canvasContext.fillStyle = "#fff"; canvasContext.arc(0, 0, 2 * rem, 0, 2 * Math.PI, false); canvasContext.fill(); canvasContext.restore(); }

    9.  绘制函数

    clearRect() 清空给定矩形内的指定像素,每次绘制的画面都不相同,避免画面叠加。

    function draw(){ canvasContext.clearRect(0, 0, canvasWidth, canvasHeight); var now = new Date(); var hour = now.getHours(); var minutes = now.getMinutes(); var seconds = now.getSeconds(); drawBackground(); drawHour(hour, minutes, seconds); drawMinute(minutes, seconds); drawSeconds(seconds); drawDot(); canvasContext.restore(); }

    10.  执行绘制函数

    实际上这种方法的绘制总会比系统时间慢一点,因为还有毫秒的误差没有处理。

    draw(); setInterval(draw, 1000);

     

     

     

     

     

     

     

     

     

    最新回复(0)