微信小程序开发之——时针-实现(2)

一 概述

  • 绘制表盘(外大圆和中心小圆)
  • 绘制大刻度(12个刻度值)和48个小刻度
  • 绘制1-12数字文字
  • 绘制时钟时针、分针、秒针
  • 定时器,每隔1s绘制一次

二 时钟实现

2.1 布局文件(index.wxml)

1
<canvas canvas-id="myCanvas" class="mycanvas"></canvas>

2.2 样式文件(index.wxss)

1
2
3
4
5
.mycanvas{
width: 100%;
height: 100%;
position: fixed;
}

2.3 逻辑文件(index.js)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// pages/index/index.js
Page({
width: 0, //窗口宽度
height: 0, //窗口高度
timer: null, //定时器

/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
//获取系统信息
wx.getSystemInfo({
success: (res) => {
this.width = res.windowWidth
this.height = res.windowHeight
},
})
},

/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
//创建ctx实例
var ctx = wx.createCanvasContext('myCanvas')
//将角度转换为弧度,方便在后面使用
//计算公式:弧度=角度*Math.PI/180
const D6 = 6 * Math.PI / 180
const D30 = 30 * Math.PI / 180
const D90 = 90 * Math.PI / 180
//获取宽和高度
var width = this.width
var height = this.height
//计算表盘半径,留出30px外边距
var radius = width / 2 - 30
//每秒绘制一次
draw()
this.timer = setInterval(draw, 1000)

function draw() {
//设置坐标轴原点为窗口的中心点
ctx.translate(width / 2, height / 2)
//绘制表盘
drawClock(ctx, radius)
//绘制指针
drawHand(ctx, radius)
//执行绘制
ctx.draw()
}

//绘制表盘
function drawClock(ctx, radius) {
//绘制大圆
ctx.setLineWidth(2) //设置线条的粗细,单位px
ctx.beginPath() //开始一个新路径
ctx.arc(0, 0, radius, 0, 2 * Math.PI, true) //圆心x,y坐标,radius:半径,0,起始角度,2*Math.PI:结束角度,true:顺时针
ctx.stroke() //开始绘制

//绘制中心圆
ctx.setLineWidth(1) //设置中心圆的粗细
ctx.beginPath() //开始一个新路径
ctx.arc(0, 0, 8, 0, 2 * Math.PI, true) //半径8
ctx.stroke()

//绘制大刻度盘
ctx.setLineWidth(5)
for (var i = 0; i < 12; i++) {
//以原点为中心顺时针旋转(多次调用旋转的角度会叠加)
ctx.rotate(D30) //360/12=30
ctx.beginPath()
ctx.moveTo(radius, 0)
ctx.lineTo(radius - 15, 0) //大刻度长度为15px
ctx.stroke()
}
//绘制小刻度盘
ctx.setLineWidth(1)
for (var i = 0; i < 60; i++) {
ctx.rotate(D6) //360/60=6
ctx.beginPath()
ctx.moveTo(radius, 0)
ctx.lineTo(radius - 10, 0) //小刻度盘长度10px
ctx.stroke()
}

//绘制文本
ctx.setFontSize(20) //字号
ctx.textBaseLine = 'middle' //文本上下居中

//文本距离时钟中心点半径
var r = radius - 30
for (var i = 1; i <= 12; i++) {
//利用三角函数计算文本坐标
var x = r * Math.cos(D30 * i - D90)
var y = r * Math.sin(D30 * i - D90)
if (i > 10) { //调整11和12的位置
//在画布上绘制文本,fillText(文本,左上角x坐标,左上角y坐标)
ctx.fillText(i, x - 12, y)
} else {
ctx.fillText(i, x - 6, y)
}
}
}
//绘制指针
function drawHand(ctx, radius) {
var t = new Date() //获取当前时间
var h = t.getHours() // 小时
var m = t.getMinutes() // 分
var s = t.getSeconds() // 秒

h = h > 12 ? h - 12 : h //将24小时制转换为12小时制

//时间从3点开始,逆时针旋转90度,指向12点
ctx.rotate(-D90)

//绘制时针
ctx.save() //记录旋转状态
ctx.rotate(D30 * (h + m / 60) + s / 3600)
ctx.setLineWidth(6)
ctx.beginPath() //开始绘制
ctx.moveTo(-20, 0) //线条起点(指针留出20px)
ctx.lineTo(radius / 2.6, 0) //线条长度
ctx.stroke()
ctx.restore() //恢复旋转状态,避免旋转叠加

//绘制分针
ctx.save()
ctx.rotate(D6 * (m + s / 60))
ctx.setLineWidth(4)
ctx.beginPath() //开始绘制
ctx.moveTo(-20, 0)
ctx.lineTo(radius / 1.8, 0)
ctx.stroke()
ctx.restore()

//绘制秒针
ctx.save()
ctx.rotate(D6*s)
ctx.setLineWidth(2)
ctx.beginPath()
ctx.moveTo(-20, 0)
ctx.lineTo(radius / 1.6, 0)
ctx.stroke()
ctx.restore()
}
},
//页面卸载,清除画布绘制定时器
onUnload: function () {
clearInterval(this.timer)
}
})

2.4 效果图

三 参考源码

  • 参考源码