基于HTML5 Canvas实现炫酷钟表效果

简介: 基于HTML5 Canvas实现炫酷钟表效果

前言

HTML5支持的canvas可以在Web中画各种相对复杂的图案,只要你愿意,前端不需要美工设计再提供任何切图!废话不多说,进入正题,本文将给大家介绍通过HTML5 Canvas实现炫酷钟表效果。

正文

分解步骤

首先先到网上随便找一个钟表的图片当作本文的设计图。

这个图表的渲染可以分为几个大的方向,钟表的轮盘,钟表的刻度和上面的数字,钟表指针和中间的圆心,这样钟表大概的步骤就完成了,最后再实现钟表转动的动画这个就算完成了。

画布初始化

使用2d上下文建立画布

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>基于canvas实现clock效果</title>
</head>
<body>
    <canvas id="clock" width="200" height="200"></canvas>
</body>
<script src="./clock.js"></script>
</html>
var drawing = document.getElementById('clock'), context;

定义常量

定义常量的目的是为了增强这个钟表样式的可配置性和可维护性,之后函数可能会大量用到的常量定义如下:

const radius = 4, // 指数圈半径
    radius1 = 100, // 圆1半径(这里圆1的直径需要为画布width的一半, 不然下面刻度的部分可能对不上)
    radius2 = 90, // 圆2半径
    radius3 = 83, // 圆3半径
    fontRadius = 65, // 字体距圆心的距离
    hourWidth = 5, // 时针宽度
    hourHeight = 55, // 时针高度
    hourShadow = 2; // 时针阴影
    minuteWidth = 3, // 分针宽度
    minuteHeight = 68, // 分针高度
    minuteShadow = 1; // 分针阴影
    secondWidth = 1, // 秒针宽度
    secondHeight = 80, // 秒针高度
    secondShadow = 0.5; // 秒针阴影

工具类函数

这里定义了sin,cos和degTolength函数,具体的说明已经写在注释里了,为什么要定义sin,cos?Math库里不是有现成的,因为太久没写数学题了,额,有点分不清sin,cos的正负,所以为了后面函数绘制计算的方便,便转换成了角度并且取了字符串

/**
 * 把sin值封装成绝对正数,因为我不记得什么时候取负数了,头皮发麻
 * @params num 度数
 */
function sin(num){
    return Math.abs(Math.sin(degTolength(num)));
}
/**
 * 把cos值封装成绝对正数
 * @params num 度数
 */
function cos(num){
    return Math.abs(Math.cos(degTolength(num)));
}
/**
 * 度数转弧度
 */
function degTolength(num){
    return num * (2 * Math.PI / 360);
}

绘制钟表轮框

钟表轮框不难看出,由三个圆叠加形成,第一个是白变黑的渐变色,第二个是黑灰渐变色,第三个橘黄变黄的渐变色

/**
 * 钟表轮框
 */
function paintClockBorder(){
    // 先画一个圈圈出来
    context.beginPath();
    context.arc(100, 100, radius1, 0, 2 * Math.PI, false);
    // 调个白变黑渐变色
    var fTo0 = context.createLinearGradient(-50, 100, 200, 100);
    fTo0.addColorStop(0, '#fff');
    fTo0.addColorStop(1, '#000');
    // 第一个最外面的圈圈搞定
    context.fillStyle = fTo0;
    context.fill();
    // 咱开始画第二个圈圈
    context.beginPath();
    context.arc(100, 100, radius2, 0, 2 * Math.PI, false);
    // 搞个黑灰渐变色
    var bTod = context.createLinearGradient(10, 100, 190, 100);
    bTod.addColorStop(0, '#000');
    bTod.addColorStop(1, '#39452D');
    context.fillStyle = bTod;
    context.fill();
    // 终于搞第三个圈圈了
    context.beginPath();
    context.arc(100, 100, radius3, 0, 2 * Math.PI, false);
    // 调个橘黄to黄渐变
    var oToy = context.createLinearGradient(20, 70, 180, 170);
    oToy.addColorStop(0, '#E17101');
    oToy.addColorStop(1, '#FFF507');
    // 第三个圈圈搞定
    context.fillStyle = oToy;
    context.fill();
}

钟表指数

这里主要就是初中数学的三角sin,cos的计算吧,唯一要注意的就是因为我取了绝对值,所以要分四个区间去渲染

/**
 * 钟表指数
 */
function paintClockSign(){
    context.beginPath();
    // 咱先画大的,每10分钟的,注意要分四个区间去渲染
    for(let i = 0; i < 12; i++){
        // 每加一个就加30deg
        if(i < 3){
            context.moveTo(radius1 + radius3 * sin(30 * i) + radius, radius1 - radius3 * cos(30 * i));
            context.arc(radius1 + radius3 * sin(30 * i), radius1 - radius3 * cos(30 * i), radius, 0, 2 * Math.PI, false);
        }else if(i >= 3 && i < 6){
            context.moveTo(radius1 + radius3 * sin(30 * i) + radius, radius1 + radius3 * cos(30 * i));
            context.arc(radius1 + radius3 * sin(30 * i), radius1 + radius3 * cos(30 * i), radius, 0, 2 * Math.PI, false);
        }else if(i >= 6 && i < 9){
            context.moveTo(radius1 - radius3 * sin(30 * i) + radius, radius1 + radius3 * cos(30 * i));
            context.arc(radius1 - radius3 * sin(30 * i), radius1 + radius3 * cos(30 * i), radius, 0, 2 * Math.PI, false);
        }else{
            context.moveTo(radius1 - radius3 * sin(30 * i) + radius, radius1 - radius3 * cos(30 * i));
            context.arc(radius1 - radius3 * sin(30 * i), radius1 - radius3 * cos(30 * i), radius, 0, 2 * Math.PI, false);
        }
    }
    context.fillStyle = '#000';
    context.fill();
    // 然后咱画一下分钟的,分钟的每加一个是加6deg
    context.beginPath();
    for(let i = 0; i < 60; i++){
        if(i < 15){
            context.moveTo(radius1 + (radius3 - radius) * sin(6 * i), radius1 - (radius3 - radius) * cos(6 * i));
            context.lineTo(radius1 + radius3 * sin(6 * i), radius1 - radius3 * cos(6 * i));
        }else if(i >= 15 && i < 30){
            context.moveTo(radius1 + (radius3 - radius) * sin(6 * i), radius1 + (radius3 - radius) * cos(6 * i));
            context.lineTo(radius1 + radius3 * sin(6 * i), radius1 + radius3 * cos(6 * i));
        }else if(i >= 30 && i < 45){
            context.moveTo(radius1 - (radius3 - radius) * sin(6 * i), radius1 + (radius3 - radius) * cos(6 * i));
            context.lineTo(radius1 - radius3 * sin(6 * i), radius1 + radius3 * cos(6 * i));
        }else{
            context.moveTo(radius1 - (radius3 - radius) * sin(6 * i), radius1 - (radius3 - radius) * cos(6 * i));
            context.lineTo(radius1 - radius3 * sin(6 * i), radius1 - radius3 * cos(6 * i));
        }
    }
    context.strokeStyle = '#AD9300';
    context.stroke();
    // 最后我们开始写度数的字
    context.font = '20px Arial';
    context.textAlign = 'center';
    context.textBaseline = 'middle';
    for(let i = 1; i <= 12; i++){
        if(i <= 3){
            context.fillText(i, radius1 + fontRadius * sin(30 * i), radius1 - fontRadius * cos(30 * i));
        }else if(i > 3 && i <= 6){
            context.fillText(i, radius1 + fontRadius * sin(30 * i), radius1 + fontRadius * cos(30 * i));
        }else if(i > 6 && i <= 9){
            context.fillText(i, radius1 - fontRadius * sin(30 * i), radius1 + fontRadius * cos(30 * i));
        }else{
            context.fillText(i, radius1 - fontRadius * sin(30 * i), radius1 - fontRadius * cos(30 * i));
        }
    }
}

绘制钟表指针

用到最关键的是rotate,先绘制竖直的矩形,再进行旋转,不过在调用rotate的时候需要先把原点换到圆心的位置

/**
 * 钟表指针
 */
function paintClockPointer(){
    let hour = new Date().getHours(),
        minute = new Date().getMinutes(),
        second = new Date().getSeconds();
    context.beginPath();
    context.fillStyle = '#fff';
    // 搞个阴影吧,不搞阴影太丑了。
    context.shadowBlur = 4;
    context.shadowColor = '#B97C29';
    // 先把画布原点换到圆心,因为得绕中心旋转
    context.translate(radius1, radius1);
    // 先时针吧,时针得粗一点
    context.shadowOffsetX = hourShadow;
    context.shadowOffsetY = hourShadow;
    context.rotate(degTolength(hour * 30));
    context.fillRect(- 2.5, - hourHeight + 10, hourWidth, hourHeight);
    // 分针
    context.shadowOffsetX = minuteShadow;
    context.shadowOffsetY = minuteShadow;
    context.rotate(degTolength( - hour * 30 + minute * 6));
    context.fillRect(- 2.5, - minuteHeight + 10, minuteWidth, minuteHeight);
    //秒针
    context.shadowOffsetX = secondShadow;
    context.shadowOffsetY = secondShadow;
    context.rotate(degTolength(- ( - hour * 30 + minute * 6) + second * 6));
    context.fillRect(- 2.5, - secondHeight + 10, secondWidth, secondHeight);
    // 圆心画个小黑点吧
    context.beginPath();
    context.arc(0 ,0 ,1 ,0, 2 * Math.PI, false);
    context.fillStyle = '#000';
}

钟表动画

经过上面的部分钟表的静态就已经完成了,并且会和目前时间同步,但是动画怎么实现呢,这里采取的方式清空画布,重新渲染,并把这个过程放入定时函数来实现钟表的动画

// 判断浏览器是否支持canvas
if(drawing.getContext){
    context = drawing.getContext('2d');
    setInterval(paintClock, 1000);
}
/**
 * 绘制钟表
 */
function paintClock(){
  // 清空画布
    context.height = context.height;
    // 保存初始的配置,颜色,画布圆心,旋转度数等
    context.save();
    paintClockBorder();
    paintClockSign();
    paintClockPointer();
    // 重置配置
    context.restore();
}

小结

到这里,基于HTML5 Canvas实现炫酷钟表效果就结束了, 具体效果如下动图


附上github链接:github.com/czm129043370

有需要的小伙伴可以自取,觉得不错别忘了给个star哈




小伙伴们今天的学习就到这里了,如果觉得本文对你有帮助的话,欢迎转发,评论,收藏,点赞!!!

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

热门文章

最新文章