前言:
DevEco Studio版本:4.0.0.600
关注过我的小伙伴一定知道我之前写过一篇基于Android的 仿抖音效果的数字时钟罗盘 最近看了鸿蒙的Canvas组件,今天通过Canvas组件也实现下罗盘数字时钟的效果。
参考链接:OpenHarmony Canvas OpenHarmony Canvasrenderingcontext2d
效果:
实现原理分析
之前安卓实现是通过matrix矩阵的方式实现,但是在鸿蒙(API10)中暂时没有给画笔设置矩阵的方法。通过查找CanvasRenderingContext2D的方法,发现rotate方法比较符合要求。
已知圆形的整个弧度为:2 * Math.PI,那么每一秒的弧度为:2 * Math.PI / 60 * (每一秒所占弧度的比例)
通过for循环可得到每一秒的弧度需要旋转的弧度为:
rotate(2 * Math.PI / 60 * (index + 1 ) //index数组角标
为了使时分秒保持在右侧水平线上,就只能通过旋转坐标系来保持当前时间所在X轴坐标系一直在原始0或60秒的那个坐标系上,那么旋转的弧度为:2 * Math.PI / 60 * (每一秒所占弧度的比例 - 当前秒值所占弧度的比例)
通过for循环可得到每一秒的弧度在原始X轴方向为:
rotate(2 * Math.PI / 60 * (index + 1 - second))//index数组角标
同理可得分钟的每一分的弧度在原始X轴方向为:
rotate(2 * Math.PI / 60 * (index + 1 - minute))
时钟的每一时的弧度在原始X轴方向为:
rotate(2 * Math.PI / 12 * (index + 1 - hour))
代码实现:
1、Canvas创建
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
@State canvasWidth: number = 500 // 500是表盘默认大小
private radius: number = 40 // 默认表盘半径
build() {
Stack({ alignContent: Alignment.Center }) {
Canvas(this.context)
.padding({ top: 76 })
.width(this.canvasWidth)
.height(this.canvasWidth + HEIGHT_ADD)
.onReady(() => {
})
}
.width('100%')
.height('100%')
.backgroundColor(Color.Black)
}
2、定时器每隔一秒获取时间
Canvas(this.context)
.padding({ top: 76 })
.width(this.canvasWidth)
.height(this.canvasWidth + HEIGHT_ADD)
.onReady(() => {
//添加setInterval定时器,每隔1s执行一次updateTime函数
this.intervalId = setInterval(this.updateTime, 1000)
})
updateTime = () => {
this.context.clearRect(0, 0, this.canvasWidth, this.canvasWidth + HEIGHT_ADD)
let nowTime = new Date()
let hour = nowTime.getHours()
let minute = nowTime.getMinutes()
let second = nowTime.getSeconds()
console.info("22222222222 hour: " + hour + " minute: " + minute + " second: " + second)
this.context.translate(this.canvasWidth / 2, this.canvasWidth / 2) //移动当前坐标系的原点
this.drawTime(hour, minute, second)
this.context.translate(-this.canvasWidth / 2, -this.canvasWidth / 2) //当前坐标系的原点复原
}
3、数据初始化
const hours: Array<string> = ["一点", "二点", "三点", "四点", "五点", "六点", "七点", "八点", "九点", "十点", "十一点", "十二点"];
const minutes: Array<string> = ["一分", "二分", "三分", "四分", "五分", "六分", "七分", "八分", "九分", "十分", "十一分", "十二分", "十三分", "十四分", "十五分", "十六分", "十七分", "十八分", "十九分",
"二十分", "二十一分", "二十二分", "二十三分", "二十四分", "二十五分", "二十六分", "二十七分", "二十八分", "二十九分", "三十分", "三十一分", "三十二分", "三十三分", "三十四分", "三十五分", "三十六分",
"三十七分", "三十八分", "三十九分", "四十分", "四十一分", "四十二分", "四十三分", "四十四分", "四十五分", "四十六分", "四十七分", "四十八分", "四十九分", "五十分", "五十一分", "五十二分", "五十三分",
"五十四分", "五十五分", "五十六分", "五十七分", "五十八分", "五十九分", ""];
const seconds: Array<string> = ["一秒", "二秒", "三秒", "四秒", "五秒", "六秒", "七秒", "八秒", "九秒", "十秒", "十一秒", "十二秒", "十三秒", "十四秒", "十五秒", "十六秒", "十七秒", "十八秒", "十九秒",
"二十秒", "二十一秒", "二十二秒", "二十三秒", "二十四秒", "二十五秒", "二十六秒", "二十七秒", "二十八秒", "二十九秒", "三十秒", "三十一秒", "三十二秒", "三十三秒", "三十四秒", "三十五秒", "三十六秒",
"三十七秒", "三十八秒", "三十九秒", "四十秒", "四十一秒", "四十二秒", "四十三秒", "四十四秒", "四十五秒", "四十六秒", "四十七秒", "四十八秒", "四十九秒", "五十秒", "五十一秒", "五十二秒", "五十三秒",
"五十四秒", "五十五秒", "五十六秒", "五十七秒", "五十八秒", "五十九秒", ""];
4、绘制时分秒
drawTime(hour: number, minute: number, second: number) {
this.context.save()
hours.forEach((value, index) => {
this.context.fillStyle = (hour % 12) == (index + 1) ? '#0080DC' : '#FFFFFF'
this.context.font = (hour % 12) == (index + 1) ? '16px' : "14px"
this.context.textAlign = "start"
this.context.textBaseline = "middle"
this.context.rotate(2 * Math.PI / 12 * (index + 1 - hour))
this.context.fillText(value, this.radius + 30, 0)
this.context.rotate(-2 * Math.PI / 12 * (index + 1 - hour))
this.context.save()
this.context.restore()
})
minutes.forEach((value, index) => {
this.context.fillStyle = minute == (index + 1) ? '#0080DC' : '#FFFFFF'
this.context.font = minute == (index + 1) ? '16px' : "14px"
this.context.textAlign = "start"
this.context.textBaseline = "middle"
this.context.rotate(2 * Math.PI / 60 * (index + 1 - minute))
this.context.fillText(value, this.radius + 70, 0)
this.context.rotate(-2 * Math.PI / 60 * (index + 1 - minute))
this.context.save()
this.context.restore()
})
seconds.forEach((value, index) => {
this.context.fillStyle = second == (index + 1) ? '#0080DC' : '#FFFFFF'
this.context.font = second == (index + 1) ? '16px' : "14px"
this.context.textAlign = "start"
this.context.textBaseline = "middle"
this.context.rotate(2 * Math.PI / 60 * (index + 1 - second))
this.context.fillText(value, this.radius + 120, 0)
this.context.rotate(-2 * Math.PI / 60 * (index + 1 - second))
this.context.save()
this.context.restore()
})
}
标签:控件,rotate,自定义,鸿蒙,index,canvasWidth,context,PI,Math
From: https://blog.csdn.net/Abner_Crazy/article/details/136875511