Html5基于Canvas画一个动态时钟


前言

Canvas API 提供了一个通过JavaScript 和 HTML的元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。

Canvas API主要聚焦于2D图形。而同样使用元素的 WebGL API 则用于绘制硬件加速的2D和3D图形。


一、前期准备

  1. HTML 页面添加一个Canvas容器,并设置好宽高。
    <canvas id="clock" width="300" height="300">
        你的浏览器不支持Canvas
    </canvas>
  1. 设置canvas的CSS样式
canvas {
    border: 1px solid red;
}
  1. 页面加载完成之后,获取canvas对象
window.addEventListener("load", function () {
    canvas = document.getElementById('clock');
    if (!canvas.getContext) {
        return;
    }
    //去除透明度
    ctx = canvas.getContext('2d', { alpha: false });
    //移动中心
    ctx.translate(canvas.width / 2, canvas.height / 2);
    //设置钟表半径
    clockRadius = Math.min(canvas.width, canvas.height) / 2;
    //调整路径结束点样式
    ctx.lineCap = "round";
    //开始绘制
    startDraw();
});

注意:

  1. canvas的属性设置的宽高是canvas的像素的宽高,也就是说设置的是canvas容器的像素,比如这里的宽高个设置的为300,即canvas被设置为一个300*300的容器。
  2. 通过CSS设置的宽高,为canvas元素放置于页面时所占的宽高,会缩放canvas容器,其对画布内部的像素没有影响。
  3. 因为我们这个Demo没有透明度的要求,所以这里获取canvas对象时取消了透明度。
  4. 钟表是以中心为原点,所以我们移动canvas的中心,并设置钟表半径为最小边一半的大小。

二、绘制刻度

1.流程

function drawCalibration() {
    ctx.strokeStyle = "black";
    for (var i = 0; i < 60; i++) {
        ctx.beginPath();
        var theta = i * (Math.PI * 2) / 60;
        var x = clockRadius * Math.cos(theta);
        var y = clockRadius * Math.sin(theta);
        ctx.moveTo(x, y);
        if (i % 5 == 0) {
            ctx.lineWidth = hoursCalibrationWidth;
            ctx.lineTo(0.85 * x, 0.85 * y);
        } else {
            ctx.lineWidth = minutesCalibrationWidth;
            ctx.lineTo(0.95 * x, 0.95 * y);
        }
        ctx.stroke();
    }
}
  1. 首先我们把路径颜色设置为黑色。
  2. 一般我们钟表会有60个刻度,其中12个时针刻度,48个分针刻度,故我们把钟表圆盘等分为60等份,5的倍数的刻度即是我们的时针刻度,其余为分针刻度。
  3. 此时,我们求出每个刻度的弧度值,并根据该刻度求出每个刻度在圆边的坐标,移动路径起点到该坐标。
  4. 当为5的倍数时,我们求得原点到圆边坐标0.85部分的坐标,并连接两点。
  5. 当不为5的倍数时,我们求得原点到圆边坐标0.95部分的坐标,并连接两点。
  6. 绘制所有路径。

2.效果图

在这里插入图片描述


三、绘制文字

1.流程

function drawHourText() {
    ctx.fillStyle = "black";
    ctx.font = "20px Arial";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    for (var i = 1; i <= 12; i++) {
        var theta = (i - 3) * (Math.PI * 2) / 12;
        var x = clockRadius * 0.75 * Math.cos(theta);
        var y = clockRadius * 0.75 * Math.sin(theta);
        ctx.fillText(i, x, y);
    }
}
  1. 首先我们设置绘制文字的基本设置。
  2. 一般钟表只会绘制12个小时的时间,故我们只取12个时间点,所以应该表盘分为12份。
  3. canvas坐标体系中,角度是一般我们现实理解的钟表当中的3点,而此处我们循环以1开头的,画的应该是30度的坐标,也就是钟表当中的4点,而我们把1这个数字画到了钟表当中的4点的位置,所以我们需要把它移动到正常钟表中的1点的位置,故把i减去3即可 ,即逆向旋转90度,然后整个圆是分为12份,所以除以12。
  4. 现在我们需要的是求我们绘制文字的坐标位置,原理和上面绘制刻度一样,只不过我们绘制的文字的坐标是以原点为圆心,到圆边0.75的位置。
  5. 最后绘制我们的文字。

2.效果图

在这里插入图片描述


四、绘制指针

1.取得当前时间

function drawDateTime() {
    ctx.strokeStyle = "black";
    var date = new Date();
    drawHoursLine(date.getHours());
    drawMinutesLine(date.getMinutes());
    drawSecondsLine(date.getSeconds());
}

2.绘制秒针

function drawSecondsLine(seconds) {
    ctx.beginPath();
    ctx.lineWidth = secondsLineWidth;
    var theta = (seconds - 15) * (Math.PI * 2) / 60;
    var x = clockRadius * Math.cos(theta);
    var y = clockRadius * Math.sin(theta);
    ctx.moveTo(-0.20 * x, -0.20 * y);
    ctx.lineTo(0.65 * x, 0.65 * y);
    ctx.stroke();
}
  1. 我们要绘制秒针,首先需要一个时间的秒数,此处有外部传进来。
  2. 由绘制文字部分我们应该了解到了canvas的坐标体系相关的问题,但是秒针是60个刻度的,所以我们要逆向旋转90度,需要减去15,然后整个圆是分为60份,所以除以60。
  3. 求得当前角度的在圆边上的点,然后找到距线圆心到圆边的向量中为-0.20的位置的坐标,以这个点为路径的起始点,然后找到该向量中0.65位置的坐标的点。
  4. 连接该两点,绘制秒针。
    效果图:

3.绘制分针

function drawMinutesLine(minutes) {
    ctx.beginPath();
    ctx.lineWidth = minutesLineWidth;
    var theta = (minutes - 15) * (Math.PI * 2) / 60;
    var x = clockRadius * Math.cos(theta);
    var y = clockRadius * Math.sin(theta);
    ctx.moveTo(-0.15 * x, -0.15 * y);
    ctx.lineTo(0.50 * x, 0.50 * y);
    ctx.stroke();
}

基本绘制过程和绘制秒针一样,故不多做讲解。

4.绘制时针

function drawHoursLine(hour) {
    ctx.beginPath();
    ctx.lineWidth = hoursLineWidth;
    var theta = ((hour % 12) - 2) * (Math.PI * 2) / 12;
    var x = clockRadius * Math.cos(theta);
    var y = clockRadius * Math.sin(theta);
    ctx.moveTo(-0.10 * x, -0.10 * y);
    ctx.lineTo(0.35 * x, 0.35 * y);
    ctx.stroke();
}

基本绘制过程和绘制秒针一样,故不多做讲解。

5.效果图

在这里插入图片描述

五、绘制圆心

1.流程

function drawCenterCicle() {
    ctx.beginPath();
    ctx.fillStyle = "#999999";
    ctx.arc(0, 0, 6, 0, 2 * Math.PI);
    ctx.fill();

    ctx.beginPath();
    ctx.fillStyle = "#666666";
    ctx.arc(0, 0, 3, 0, 2 * Math.PI);
    ctx.fill();
}

这里只是个效果,没必要

2.效果图

在这里插入图片描述
到此,整个表盘已经绘制完成了,但是这仅仅是个静态的钟表,下面我们需要让他动起来

六、让钟表动起来

1.流程

function startDraw() {
    drawClock();
    interval = setInterval(function () {
        drawClock();
    }, 1000);
}

function drawClock() {
    ctx.clearRect(-clockRadius, -clockRadius, 2 * clockRadius, 2 * clockRadius);

    drawCalibration();
    drawHourText();
    
    drawDateTime();

    drawCenterCicle();
}

window.addEventListener("visibilitychange", function (event) {
    if (document.hidden) {
        window.clearInterval(interval);
        interval = null;
    } else {
        startDraw();
    }
})
  1. 首先我们创建个函数drawClock,把前面的代码整合起来,并在绘制钟表之前,清楚一下画布当中的内容。
  2. 然后创建startDraw函数,内部维护了个计时时间,间隔1秒(应该是至少一秒,JavaScript事件循环的问题)调用我们的绘制函数。
  3. 添加一个visibilitychange事件监听,当当前页面可见时,开启我们的计时事件,不可见时清楚计时器。

此时你会发现,我们的钟表跟随时间动起来了,证明我们的Demo成功了。

2.效果图

在这里插入图片描述


七、项目地址

HTML5基于Canvas绘制动态时钟

总结

本文从向量的角度绘制了钟表,并没有使用旋转画布之类的方式,其思路大家可供借鉴。

Canvas功能强大,丰富了我们的视觉体验,其不仅仅可用来绘制2D图像,还可以应用于3D图像的绘制。该文仅仅展示了它的冰山一角,需要我们仔细专研,增强我们的用户体验。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lhuann_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值