鸿蒙HarmonyOS开发实例:【简单时钟】
1.OpenHarmony南向开发案例:【智能风扇】
2.鸿蒙HarmonyOS开发实例:【简单时钟】
3.HarmonyOS开发实例:【状态管理】4.鸿蒙OS开发学习:【尺寸适配实现】5.OpenHarmony鸿蒙开发学习:【Ability的启动模式】6.鸿蒙HarmonyOS开发实战:【分布式音乐播放】7.HarmonyOS开发实例:【分布式数据管理】8.鸿蒙HarmonyOS开发实例:【分布式关系型数据库】9.OpenHarmony开发技术:【国际化】实例10.OpenHarmony开发案例:【分布式计算器】11.HarmonyOS开发实例:【数字管家app】12.HarmonyOS开发:【NFC配置流程】13.HarmonyOS开发:【数字管家app设备接入FA】14.鸿蒙OS开发实例:【HarmonyHttpClient】网络框架15.鸿蒙OS开发实例:【Native C++】16.HarmonyOS开发实例:【菜单app】17.OpenHarmony开发学习:【源码下载和编译】18.HarmonyOS开发实例:【自定义Emitter】19.鸿蒙OS开发学习:【第三方库调用】20.HarmonyOS开发学习:【DevEco Device Tool 安装配置(问题全解)】21.OpenHarmony开发实例:【鸿蒙.bin文件烧录】22.HarmonyOS开发实例:【app帐号管理】23.OpenHarmony实例应用:【常用组件和容器低代码】24.OpenHarmony南向嵌入式:【XR806开发板指导文档】25.OpenHarmony南向开发案例:【智能门锁】26.HarmonyOS开发实例:【任务延时调度】27.OpenHarmony开发案例:【自定义通知】28.OpenHarmony开发实例:【仿桌面应用】29.HarmonyOS开发实例:【事件的订阅和发布】30.OpenHarmony开发案例:【电影卡片】31.OpenHarmony南向开发案例:【智能体重秤】32.鸿蒙OS开发指导:【应用包签名工具】33.OpenHarmony开发实例:【分布式游戏鉴权应用】34.OpenHarmony开发实例:【新闻客户端】35.鸿蒙OpenHarmony Native API【Native_Bundle】36.HarmonyOS开发实战:【亲子拼图游戏】简单时钟
介绍
本示例通过使用[@ohos.display]接口以及Canvas组件来实现一个简单的时钟应用。
效果预览
使用说明
1.界面通过setInterval实现周期性实时刷新时间,使用Canvas绘制时钟,指针旋转角度通过计算得出。
例如:"2 * Math.PI / 60 * second"是秒针旋转的角度。
鸿蒙开发应用知识已更新gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
参考前往。
具体实现
鸿蒙学习文档前往mau123789是v添加即可
- 本示例展示简单时钟的方法主要封装在Index中,源码参考:[Index.ets] 。
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import display from '@ohos.display'
import Logger from '../model/Logger'
const HOURS: Array<string> = ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '1', '2']
const HEIGHT_ADD: number = 150 // 表盘下面需要绘制时间,canvas高度是宽度加150
const TAG: string = 'Index'
@Entry
@Component
struct Clock {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
@State canvasWidth: number = 300 // 300是表盘默认大小
private radius: number = 150 // 默认表盘半径
private intervalId: number = 0
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()
let time = `${this.fillTime(hour)}:${this.fillTime(minute)}:${this.fillTime(second)}`
this.drawBackGround()
this.drawHour(hour, minute)
this.drawMinute(minute)
this.drawSecond(second)
this.drawDot()
this.drawTime(time)
this.context.translate(-this.radius, -this.radius)
}
fillTime(time: number) {
return time < 10 ? `0${time}` : `${time}`
}
aboutToAppear() {
this.getSize()
}
// 获取设备宽高计算表盘大小
async getSize() {
let mDisplay = await display.getDefaultDisplay()
Logger.info(TAG, `getDefaultDisplay mDisplay = ${JSON.stringify(mDisplay)}`)
this.canvasWidth = px2vp(mDisplay.width > mDisplay.height ? mDisplay.height * 0.6 : mDisplay.width * 0.6)
this.radius = this.canvasWidth / 2
}
drawBackGround() {
// 绘制背景
let grad = this.context.createRadialGradient(this.radius, this.radius, this.radius - 32, this.radius,
this.radius, this.radius)
grad.addColorStop(0.0, 'white')
grad.addColorStop(0.9, '#eee')
grad.addColorStop(1.0, 'white')
this.context.fillStyle = grad
this.context.fillRect(0, 0, this.canvasWidth, this.canvasWidth)
// 绘制外圈圆
this.context.translate(this.radius, this.radius)
this.context.lineWidth = 6
this.context.beginPath()
this.context.strokeStyle = '#fff'
this.context.arc(0, 0, this.radius - 5, 0, 2 * Math.PI, false)
this.context.stroke()
// 绘制时间文字
this.context.font = '30px'
this.context.textAlign = "center"
this.context.textBaseline = "middle"
this.context.fillStyle = '#000'
this.context.save()
HOURS.forEach((num, index) => {
let rad = 2 * Math.PI / 12 * index
let x = Math.cos(rad) * (this.radius - 38)
let y = Math.sin(rad) * (this.radius - 38)
this.context.fillText(num, x, y)
})
this.context.restore()
// 绘制刻度
for (let i = 0; i < 60; i++) {
let rad = 2 * Math.PI / 60 * i
let x = Math.cos(rad) * (this.radius - 12)
let y = Math.sin(rad) * (this.radius - 12)
this.context.beginPath()
this.context.moveTo(x, y)
if (i % 5 == 0) {
let x1 = Math.cos(rad) * (this.radius - 20)
let y1 = Math.sin(rad) * (this.radius - 20)
this.context.strokeStyle = '#000'
this.context.lineWidth = 2
this.context.lineTo(x1, y1)
} else {
let x1 = Math.cos(rad) * (this.radius - 18)
let y1 = Math.sin(rad) * (this.radius - 18)
this.context.strokeStyle = '#ccc'
this.context.lineWidth = 1
this.context.lineTo(x1, y1)
}
this.context.stroke()
}
this.context.restore()
}
// 绘制时针
drawHour(hour: number, minute: number) {
this.context.save()
this.context.beginPath()
this.context.lineWidth = 8
this.context.lineCap = 'round'
let rad = 2 * Math.PI / 12 * hour
let mrad = 2 * Math.PI / 12 / 60 * minute
this.context.rotate(rad + mrad)
this.context.moveTo(0, 10)
this.context.strokeStyle = '#000'
this.context.lineTo(0, -this.radius / 2)
this.context.stroke()
this.context.restore()
}
// 绘制分针
drawMinute(minute: number) {
this.context.save()
this.context.beginPath()
this.context.lineWidth = 5
this.context.lineCap = 'round'
let rad = 2 * Math.PI / 60 * minute
this.context.rotate(rad)
this.context.moveTo(0, 10)
this.context.strokeStyle = '#000'
this.context.lineTo(0, -this.radius + 40)
this.context.stroke()
this.context.restore()
}
// 绘制秒针
drawSecond(second: number) {
this.context.save()
this.context.beginPath()
this.context.lineWidth = 2
this.context.lineCap = 'round'
let rad = 2 * Math.PI / 60 * second
this.context.rotate(rad)
this.context.moveTo(0, 10)
this.context.strokeStyle = '#05f'
this.context.lineTo(0, -this.radius + 21)
this.context.stroke()
this.context.restore()
}
// 绘制中心点
drawDot() {
this.context.save()
this.context.beginPath()
this.context.fillStyle = '#05f'
this.context.arc(0, 0, 4, 0, 2 * Math.PI, false)
this.context.fill()
this.context.restore()
}
// 绘制表盘下面时间文本
drawTime(time: string) {
this.context.save()
this.context.beginPath()
this.context.font = '90px'
this.context.textAlign = "center"
this.context.textBaseline = "middle"
this.context.fillStyle = '#000'
this.context.fillText(time, 0, this.radius + 80)
this.context.restore()
}
build() {
Stack({ alignContent: Alignment.Center }) {
Canvas(this.context)
.padding({ top: 76 })
.width(this.canvasWidth)
.height(this.canvasWidth + HEIGHT_ADD)
.onReady(() => {
this.updateTime()
this.intervalId = setInterval(this.updateTime, 1000)
})
}
.width('100%')
.height('100%')
}
onPageHide() {
clearInterval(this.intervalId)
}
aboutToDisappear(){
clearInterval(this.intervalId)
}
}
- 设置表盘大小:通过Index中的display.getDefaultDisplay()方法来获取设备宽高计算表盘大小;
- 获取当前时间:调用updateTime函数,执行new Date().getHours()、new Date().getMinutes()、new Date().getSeconds()获取当前时间。
- 绘制表盘内容:通过[CanvasRenderingContext2D] 来画表盘背景、时针、分针、秒针、圆心以及表盘下方文本;
- 启动时钟:添加setInterval定时器,每隔1s执行一次updateTime函数。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了