学了一天Canvas,画了个Clock

214 阅读1分钟

image.png

一直很好奇Canvas,以前也没用过,今天专门对着MDN的文档认真学了大半天,大概了解了它的Api,一天快结束了,画个钟吧。想到以前学习CSS动画,最后也是画了个钟。

Clock,确实是很有代表性的东西

大部分代码找着MDN文档Copy的,尝试改了下UI,唯一突破就是加了数字。

因为要加数字,还专门去搜索如何计算圆周上点的坐标, 又是sin,cos,当年我的三角函数学得还不错,如今全忘了。

看到transform这个API,又去温习了一下矩阵,大学线性代数没学好有点可惜,还想起来那个女老师,名字我都没忘记。好吧,实际上我连矩阵乘法都忘的干干净净了。

Canvas的api不复杂,但是要想用好,还得数学好呀,突然觉得好难,又是从入门到放弃的一天,害~

<script setup lang="ts">
import { ref, onMounted } from 'vue'

const canvasRef = ref()
let ctx: any = null

onMounted(() => {
  ctx = canvasRef.value.getContext('2d')
  clock()
})
function clock() {
  var now = new Date()

  ctx.save()
  ctx.clearRect(0, 0, 500, 500)
  ctx.translate(200, 200)
  // ctx.scale(1, 1)
  ctx.rotate(-Math.PI / 2)
  ctx.strokeStyle = '#b9b9b9'
  ctx.fillStyle = '#b9b9b9'
  ctx.lineWidth = 4
  ctx.lineCap = 'round'
  ctx.lineCap = 'square'

  ctx.arc(0, 0, 150, 0, Math.PI * 2, true)
  ctx.fillStyle = '#4d4d4d'
  ctx.fill()

  // Hour marks
  ctx.save()
  for (var i = 0; i < 12; i++) {
    ctx.beginPath()
    ctx.rotate(Math.PI / 6)
    ctx.moveTo(136, 0)
    ctx.lineTo(142, 0)
    ctx.stroke()
  }
  ctx.restore()

  // text marks
  ctx.save()
  ctx.rotate(Math.PI / 2)
  for (var i = 1; i < 13; i++) {
    ctx.font = '18px arial'
    ctx.fillStyle = '#b9b9b9'

    let text = ctx.measureText(i)
    let x = 118 * Math.cos((30 * (i - 3) * Math.PI) / 180) - text.width / 2
    let y = 118 * Math.sin((30 * (i - 3) * Math.PI) / 180) + 7

    ctx.fillText(i, x, y)
  }
  ctx.restore()

  // Minute marks
  ctx.save()
  ctx.lineWidth = 2
  ctx.stokeStyle = '#eee'
  for (i = 0; i < 60; i++) {
    if (i % 5 != 0) {
      ctx.beginPath()
      ctx.moveTo(138, 0)
      ctx.lineTo(142, 0)
      ctx.stroke()
    }
    ctx.rotate(Math.PI / 30)
  }
  ctx.restore()

  var sec = now.getSeconds()
  var min = now.getMinutes()
  var hr = now.getHours()
  hr = hr >= 12 ? hr - 12 : hr

  ctx.fillStyle = 'black'

  // write Hours
  ctx.save()
  ctx.rotate(hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) * sec)
  ctx.lineWidth = 8
  ctx.beginPath()
  ctx.moveTo(-20, 0)
  ctx.lineTo(80, 0)
  ctx.strokeStyle = '#222'
  ctx.stroke()
  ctx.beginPath()
  ctx.moveTo(30, 0)
  ctx.lineTo(80, 0)
  ctx.strokeStyle = '#eee'
  ctx.stroke()
  ctx.restore()

  // write Minutes
  ctx.save()
  ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec)
  ctx.lineWidth = 6
  ctx.beginPath()
  ctx.moveTo(-28, 0)
  ctx.lineTo(30, 0)
  ctx.strokeStyle = '#222'
  ctx.stroke()
  ctx.beginPath()
  ctx.moveTo(30, 0)
  ctx.lineTo(100, 0)
  ctx.strokeStyle = '#eee'
  ctx.stroke()
  ctx.restore()

  // Write seconds
  ctx.save()
  ctx.rotate((sec * Math.PI) / 30)
  ctx.strokeStyle = '#D40000'
  ctx.fillStyle = '#D40000'
  ctx.lineWidth = 3
  ctx.beginPath()
  ctx.moveTo(-30, 0)
  ctx.lineTo(90, 0)
  ctx.stroke()

  ctx.beginPath()
  ctx.arc(0, 0, 10, 0, Math.PI * 2, true)
  ctx.fill()
  ctx.beginPath()
  ctx.arc(95, 0, 5, 0, Math.PI * 2, true)
  ctx.stroke()
  ctx.fillStyle = 'rgba(0,0,0,0)'
  ctx.arc(0, 0, 3, 0, Math.PI * 2, true)
  ctx.fill()
  ctx.restore()

  ctx.beginPath()
  ctx.lineWidth = 6
  ctx.strokeStyle = '#494949'
  ctx.arc(0, 0, 150, 0, Math.PI * 2, true)
  ctx.stroke()

  ctx.restore()

  window.requestAnimationFrame(clock)
}

window.requestAnimationFrame(clock)
</script>