若有收获,就点个赞吧
图片资源:
利用ArkUI的Canvas组件可以高效实现动态图形-闹钟表盘的绘制。本文将以实时时钟组件为例,展示如何通过Canvas的坐标变换与动画机制,实现高性能的动态图形渲染效果。
【实现效果】
• 操作系统:Windows 10
• 开发工具:DevEco Studio(5.0.7.210)
• 目标设备:华为Mate60 Pro
• 开发语言:ArkTS
• 框架:ArkUI
• API版本:API 14
【工程目录】
├─ entry
│ ├─ obfuscation-rules.txt
│ ├─ oh-package.json5 // 声明依赖
│ └─ src
│ ├─ main
│ │ ├─ ets
│ │ │ ├─ entryability
│ │ │ │ └─ EntryAbility.ets //程序入口类
│ │ │ ├─ entrybackupability
│ │ │ │ └─ EntryBackupAbility.ets
│ │ │ ├─ images //图片资源类
│ │ │ │ ├─ ic_clock_pan.png
│ │ │ │ ├─ ic_confirm.png
│ │ │ │ ├─ ic_hour_pointer.png
│ │ │ │ ├─ ic_minute_pointer.png
│ │ │ │ ├─ ic_public_arrow_right.svg
│ │ │ │ └─ ic_second_pointer.png
│ │ │ └─ pages
│ │ │ └─ Index.ets //主页入口
│ │ ├─ module.json5 // 模块配置相关
│ │ └─ resources // 应用静态资源
│ │ ├─ base
│ │ │ ├─ element
│ │ │ │ ├─ color.json
│ │ │ │ ├─ float.json
│ │ │ │ └─ string.json
│ │ │ ├─ media
│ │ │ │ ├─ background.png
│ │ │ │ ├─ foreground.png
│ │ │ │ ├─ layered_image.json
│ │ │ │ └─ startIcon.png
│ │ │ └─ profile
│ │ │ ├─ backup_config.json
│ │ │ └─ main_pages.json
│ │ ├─ dark
│ │ │ └─ element
│ │ │ └─ color.json
│ │ └─ rawfile
@Entry
@Component
export struct CanvasComp {
// 核心绘图对象配置
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
// 资源预加载
private panImage = new ImageBitmap("/images/ic_clock_pan.png")
private hourImage = new ImageBitmap("/images/ic_hour_pointer.png")
//...其他图片资源
}
startDraw() {
this.drawClock()
setInterval(() => {
this.drawClock()
}, 1000)
}
drawClock() {
this.context.clearRect(0, 0, this.canvasSize, this.canvasSize)
this.context.drawImage(this.panImage, 0, 0, this.canvasSize, this.canvasSize)
//...时间获取与指针绘制
}
drawPointer(img: ImageBitmap, angle: number = 0) {
this.context.save()
this.context.translate(this.canvasSize/2, this.canvasSize/2)
this.context.rotate((180 + angle) * Math.PI / 180)
//...绘制逻辑
this.context.restore()
}
build() {
Column() {//列容器组件
Canvas(this.context)
.aspectRatio(1)
.onReady(() => {
this.startDraw()
})
}
.height('100%')//列容器高度
.justifyContent(FlexAlign.Center)//表盘居中
}
完整代码:
@Entry
@Component
export struct CanvasComp {
//抗锯齿设置
private settings: RenderingContextSettings = new RenderingContextSettings(true)
//创建画布实例context
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
//绘制图片,创建ImageBitmap对象 ,时针、分针、秒针
private panImage = new ImageBitmap("/images/ic_clock_pan.png")
private hourImage = new ImageBitmap("/images/ic_hour_pointer.png")
private minuteImage = new ImageBitmap("/images/ic_minute_pointer.png")
private secondImage = new ImageBitmap("/images/ic_second_pointer.png")
//画布参数
canvasSize = 252
//时针、分针、秒针对应的宽度
pointerWidth = 8
//绘制图像:绘制表盘+设置定时
startDraw() {
//开始画图,表盘、时针、分针、秒针
this.drawClock()
setInterval(() => {
this.drawClock()
}, 1000)
}
//绘制表盘、时针、分针、秒针
drawClock() {
//清空先前的绘图
this.context.clearRect(0, 0, this.canvasSize, this.canvasSize)
//绘制表盘
this.context.drawImage(this.panImage, 0, 0, this.canvasSize, this.canvasSize)
//获取系统时间
const date = new Date()
const hour = date.getHours() + date.getMinutes() / 60 //获取系统当前小时
const minute = date.getMinutes() //获取系统当前分钟
const second = date.getSeconds() //获取系统当前秒
//绘制时针
this.drawPointer(this.hourImage, 360 * 1 / 12 * (hour % 12))
//绘制分针
this.drawPointer(this.minuteImage, 360 * 1 / 60 * minute)
//绘制秒针
this.drawPointer(this.secondImage, 360 * 1 / 60 * second)
}
//绘制表针
drawPointer(img: ImageBitmap, angle: number = 0) {
/**
* 绘制表针
*/
this.context.save() //保存
//设置旋转顶点
this.context.translate(this.canvasSize / 2, this.canvasSize / 2)
//画布、图像旋转
this.context.rotate((180 + angle) * Math.PI / 180)
//设置旋转中心
this.context.translate(-this.pointerWidth / 2, -this.canvasSize / 2)
//绘制时针
this.context.drawImage(img, 0, 0, this.pointerWidth, this.canvasSize)
//设置旋转中心
this.context.translate(this.canvasSize / 2, this.canvasSize / 2)
//重置
this.context.restore()
}
build() {
Column() {
Canvas(this.context)
.width(this.canvasSize)
.aspectRatio(1)// .backgroundColor('#ccc')
.onReady(() => {
this.startDraw()
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
若有收获,就点个赞吧
评论(0)