用 js canvas 做一个优雅的模拟时钟, canvas 教程实例

用 js canvas 做一个优雅的模拟时钟, canvas 教程实例

有很多次,我都想找到一个比较不错的,可以查看模拟时钟的网页。
有时候是想看下距离某个时间点还有多长时间,有时候是想看一下,两个时间点之间的间隔是多少。因为模拟时钟的排布比数字时钟要更直观。
但一直没有找到。

这些天闲的时候就想做个 canvas 模拟时钟玩,慢慢就做出效果来了。
目前的大致效果如下:

可访问的地址:

线上地址(白): http://kylebing.cn/tools/clock-a/
线上地址(黑): http://kylebing.cn/tools/clock-a?theme=black
github: https://github.com/KyleBing/animate-clock-canvas

在这里插入图片描述

一、需求

我对模拟时钟的需求有几个:

  • 一定要优雅,不花哨
  • 秒针一定要动的平滑,不是一秒一秒的动,而是要像 iOS 中的时钟那样
  • 优雅,还是优雅,简洁而不简单

二、实现原理:表盘

你需要具备使用 canvas 绘制简单图形的能力,不需要复杂,会画个方块、圆、文字,就可以了。
很简单,直接看 MDN 官方文档上的例子就能看明白。

CanvasRenderingContext2D: canvas property

会了基础的操作之后,就说一下粗略的实现过程:

<!DOCTYPE html>
<html lang="zh-CN">
<body>

<canvas id='canvas' width="600" height="600" style="width: 600px; height: 600px; border: 1px solid black;"></canvas>


</body>

<script>
    let canvasItem = document.querySelector('#canvas')
    let ctx = canvasItem.getContext("2d")

    ctx.fillStyle = 'magenta'
    ctx.fillRect(0,0, 5, 20)
</script>
</html>

此时画面是这样的
在这里插入图片描述

1. 画12个小时的刻度

这里需要你会对 ctx 进行旋转,Math.PI 是半个圆的旋转角度,那么整个圆12等分后,每个刻度的旋转角度就是

let rotationAngle = Math.PI * (1/6)

这里需要注意的是,当你用 ctx.rotate() 方法旋转的时候,你旋转的是整个画布,并且它不会自动恢复到原来的样子。
也就是说,如果你 rotate() 了30度,那么画布就会在后面的绘画过程中都保持在 旋转了30度的这个状态。后面画的所有内容都是旋转 30 度的。

而这不是我们想要的,我们只需要在画这个表盘的时候旋转,在绘制完成之后恢复到原来的样子。

此时就需要 ctx 的两个方法了: save() restore()
这两个方法的作用就是 save() 保存画布的一个状态,在后面再 restore() 恢复到保存状态时的状态。

比如我们在这个画布上旋转30度再写个文字试试:

<!DOCTYPE html>
<html lang="zh-CN">
<body>

<canvas id='canvas' width="600" height="600" style="width: 600px; height: 600px; border: 1px solid black;"></canvas>


</body>

<script>
    let canvasItem = document.querySelector('#canvas')
    let ctx = canvasItem.getContext("2d")

    ctx.rotate(Math.PI / 6)  // 旋转 30 度
    ctx.fillStyle = 'magenta'
    ctx.fillRect(0,0, 5, 20)

    ctx.font = '50px Impact'  // 字体设置
    ctx.fillText('Rotate 30', 100,0)  // 绘制字体
</script>
</html>

在这里插入图片描述
但是如果我们使用 save() 和 restore() 就能保证文字的角度正常了。

<!DOCTYPE html>
<html lang="zh-CN">
<body>

<canvas id='canvas' width="600" height="600" style="width: 600px; height: 600px; border: 1px solid black;"></canvas>


</body>

<script>
    let canvasItem = document.querySelector('#canvas')
    let ctx = canvasItem.getContext("2d")

    ctx.save()  // 保存旋转之前的画布状态
    ctx.rotate(Math.PI / 6)
    ctx.fillStyle = 'magenta'
    ctx.fillRect(0,0, 5, 20)

    ctx.restore()
    ctx.font = '50px Impact'
    ctx.fillText('Rotate 30', 100,50)
</script>
</html>

在这里插入图片描述

好,知道这些了就开始绘制表盘的 12 个刻度了。

    let canvasItem = document.querySelector('#canvas')
    let ctx = canvasItem.getContext("2d")

    ctx.save()  // 保存旋转之前的画布状态

    for (let i=0;i<12;i++){
   
   
        ctx.rotate(Math.PI / 6)
        ctx.fillStyle = 'magenta'
        ctx.fillRect(0,0, 5, 20)
    }

    ctx.restore()
    ctx.font = '50px Impact'
    ctx.fillText('Rotate 30', 100,50)

在这里插入图片描述

能看到上图中,这几个旋转是旋转了,但中心点不对,这里需要另外一个方法,就是 translate() ,用它将左上角的 0,0 点移动到画布的中间位置,再绘制。

let canvasItem = document.querySelector('#canvas')
let ctx = canvasItem.getContext("2d")

ctx.save()  // 保存旋转之前的画布状态

ctx.translate(300, 300) // 将 0,0 移动到画布中间

for (let i=0;i<12;i++){
   
   
    ctx.rotate(Math.PI / 6)
    ctx.fillStyle = 'magenta'
    ctx.fillRect(0,0, 5, 20)
}

ctx.restore()
ctx.font = '50px Impact'
ctx.fillText('Rotate 30', 100,50)

在这里插入图片描述

加个辅助线,再看,你应该参看到所有刻度线都没有位于中间。

let canvasItem = document.querySelector('#canvas')
let ctx = canvasItem.getContext("2d")

ctx.save()  // 保存旋转之前的画布状态

ctx.translate(300, 300) // 将 0,0 移动到画布中间

for (let i=0;i<12;i++){
   
   
    ctx.rotate(Math.PI / 6)
    ctx.fillStyle = 'magenta'
    ctx.fillRect(0,0, 10, 30)
}

ctx.restore()

drawRef
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十月ooOO

许个愿,我帮你实现

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

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

打赏作者

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

抵扣说明:

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

余额充值