news 2026/2/6 7:47:15

鸿蒙简易时钟应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙简易时钟应用

代码功能概述

这段代码实现了一个功能完整的鸿蒙时钟应用,全面展示了ArkTS在时间处理、多时区显示、闹钟设置和界面动画等方面的核心能力。主要功能包括:

  • 模拟时钟:显示带有时针、分针、秒针的模拟时钟

  • 数字时钟:显示精确到秒的数字时间

  • 多时区支持:显示不同时区的当前时间

  • 闹钟功能:设置和管理多个闹钟

  • 倒计时器:支持自定义时间的倒计时功能

  • 世界时钟:同时显示多个主要城市的时间

  • 时间设置:模拟调整系统时间

通过这个示例,可以深入理解ArkTS如何实现时间处理、动画效果和复杂的状态管理。

2. 代码逻辑分析

应用采用"时间驱动UI"的架构设计:

  1. 初始化阶段:应用启动时,初始化时间数据和多时区信息

  2. 状态管理:使用多个@State装饰器管理当前时间、时区、闹钟列表和倒计时状态

  3. 实时更新时间

    • 使用定时器每秒更新当前时间 → 刷新数字显示和模拟时钟指针

    • 多时区计算 → 根据时区偏移计算各城市时间 → 更新显示

  4. 闹钟管理

    • 添加闹钟 → 设置时间、重复规则 → 添加到闹钟列表

    • 启用/禁用闹钟 → 切换闹钟状态 → 更新界面

    • 闹钟触发 → 检查当前时间 → 显示提醒(模拟)

  5. 倒计时功能

    • 设置倒计时时间 → 启动倒计时 → 每秒更新剩余时间

    • 倒计时结束 → 触发提醒 → 重置状态

  6. 界面动画

    • 模拟时钟指针的平滑转动动画

    • 界面切换的过渡效果

完整代码

@Entry @Component struct ClockTutorial { @State currentTime: Date = new Date(); @State selectedTimezone: string = 'Asia/Shanghai'; @State isAnalogMode: boolean = true; @State alarms: Alarm[] = []; @State countdownTime: number = 0; @State isCountingDown: boolean = false; @State worldClocks: WorldClock[] = [ { city: '北京', timezone: 'Asia/Shanghai', time: '' }, { city: '纽约', timezone: 'America/New_York', time: '' }, { city: '伦敦', timezone: 'Europe/London', time: '' }, { city: '东京', timezone: 'Asia/Tokyo', time: '' } ]; aboutToAppear() { this.startClock(); this.loadSampleAlarms(); } build() { Column({ space: 0 }) { // 模式切换 this.BuildModeToggle() // 时钟显示区域 if (this.isAnalogMode) { this.BuildAnalogClock() } else { this.BuildDigitalClock() } // 世界时钟 this.BuildWorldClocks() // 功能按钮 this.BuildFunctionButtons() // 闹钟列表 this.BuildAlarmList() } .width('100%') .height('100%') .padding(20) .backgroundColor('#1A1A2E') } @Builder BuildModeToggle() { Row({ space: 20 }) { Button('模拟时钟') .onClick(() => { this.isAnalogMode = true; }) .backgroundColor(this.isAnalogMode ? '#4A90E2' : '#2D3748') .fontColor('#FFFFFF') .borderRadius(20) .padding({ left: 20, right: 20 }) .height(40) Button('数字时钟') .onClick(() => { this.isAnalogMode = false; }) .backgroundColor(!this.isAnalogMode ? '#4A90E2' : '#2D3748') .fontColor('#FFFFFF') .borderRadius(20) .padding({ left: 20, right: 20 }) .height(40) } .width('100%') .justifyContent(FlexAlign.Center) .margin({ bottom: 20 }) } @Builder BuildAnalogClock() { const hours = this.currentTime.getHours() % 12; const minutes = this.currentTime.getMinutes(); const seconds = this.currentTime.getSeconds(); Stack({ alignContent: Alignment.Center }) { // 时钟外圈 Circle({ width: 280, height: 280 }) .fill('#0F3460') .stroke('#4A90E2') .strokeWidth(4) // 时钟刻度 ForEach(Array.from({ length: 12 }), (_, index: number) => { const angle = (index * 30) * Math.PI / 180; const x1 = 140 + 120 * Math.sin(angle); const y1 = 140 - 120 * Math.cos(angle); const x2 = 140 + 130 * Math.sin(angle); const y2 = 140 - 130 * Math.cos(angle); Line() .startPoint({ x: x1, y: y1 }) .endPoint({ x: x2, y: y2 }) .strokeWidth(2) .strokeColor('#FFFFFF') }) // 时针 Line() .startPoint({ x: 140, y: 140 }) .endPoint({ x: 140 + 60 * Math.sin((hours * 30 + minutes * 0.5) * Math.PI / 180), y: 140 - 60 * Math.cos((hours * 30 + minutes * 0.5) * Math.PI / 180) }) .strokeWidth(6) .strokeColor('#FFFFFF') .lineCap(LineCapStyle.Round) // 分针 Line() .startPoint({ x: 140, y: 140 }) .endPoint({ x: 140 + 80 * Math.sin(minutes * 6 * Math.PI / 180), y: 140 - 80 * Math.cos(minutes * 6 * Math.PI / 180) }) .strokeWidth(4) .strokeColor('#4A90E2') .lineCap(LineCapStyle.Round) // 秒针 Line() .startPoint({ x: 140, y: 140 }) .endPoint({ x: 140 + 90 * Math.sin(seconds * 6 * Math.PI / 180), y: 140 - 90 * Math.cos(seconds * 6 * Math.PI / 180) }) .strokeWidth(2) .strokeColor('#FF6B6B') .lineCap(LineCapStyle.Round) // 中心点 Circle({ width: 12, height: 12 }) .fill('#FF6B6B') } .width(280) .height(280) .margin({ bottom: 20 }) } @Builder BuildDigitalClock() { Column({ space: 10 }) { Text(this.formatTime(this.currentTime)) .fontSize(64) .fontWeight(FontWeight.Bold) .fontColor('#FFFFFF') Text(this.formatDate(this.currentTime)) .fontSize(18) .fontColor('#A0AEC0') Text(this.getWeekday(this.currentTime)) .fontSize(16) .fontColor('#4A90E2') } .width('100%') .height(160) .justifyContent(FlexAlign.Center) .margin({ bottom: 20 }) } @Builder BuildWorldClocks() { Column({ space: 10 }) { Text('世界时间') .fontSize(18) .fontWeight(FontWeight.Medium) .fontColor('#FFFFFF') .alignSelf(ItemAlign.Start) .margin({ bottom: 10 }) Grid() { ForEach(this.worldClocks, (clock: WorldClock) => { GridItem() { this.BuildWorldClockItem(clock) } }) } .columnsTemplate('1fr 1fr') .rowsTemplate('1fr 1fr') .columnsGap(15) .rowsGap(15) .width('100%') } .width('100%') .margin({ bottom: 20 }) } @Builder BuildWorldClockItem(clock: WorldClock) { Column({ space: 8 }) { Text(clock.city) .fontSize(16) .fontWeight(FontWeight.Medium) .fontColor('#FFFFFF') .alignSelf(ItemAlign.Start) Text(clock.time) .fontSize(14) .fontColor('#A0AEC0') .alignSelf(ItemAlign.Start) Text(clock.timezone) .fontSize(12) .fontColor('#4A90E2') .alignSelf(ItemAlign.Start) } .width('100%') .height(80) .padding(12) .backgroundColor('#2D3748') .borderRadius(12) } @Builder BuildFunctionButtons() { Row({ space: 15 }) { Button('闹钟') .onClick(() => { this.showAlarmDialog(); }) .backgroundColor('#4A90E2') .fontColor('#FFFFFF') .borderRadius(12) .layoutWeight(1) .height(50) Button('倒计时') .onClick(() => { this.startCountdown(300); // 5分钟倒计时 }) .backgroundColor(this.isCountingDown ? '#FF6B6B' : '#2D3748') .fontColor('#FFFFFF') .borderRadius(12) .layoutWeight(1) .height(50) Button('秒表') .onClick(() => { this.startStopwatch(); }) .backgroundColor('#2D3748') .fontColor('#FFFFFF') .borderRadius(12) .layoutWeight(1) .height(50) } .width('100%') .margin({ bottom: 20 }) } @Builder BuildAlarmList() { Column({ space: 10 }) { Row({ space: 10 }) { Text('闹钟') .fontSize(18) .fontWeight(FontWeight.Medium) .fontColor('#FFFFFF') .layoutWeight(1) Text(`${this.alarms.length} 个`) .fontSize(14) .fontColor('#A0AEC0') } .width('100%') if (this.alarms.length === 0) { this.BuildEmptyState('暂无闹钟', '点击上方"闹钟"按钮添加') } else { ForEach(this.alarms.slice(0, 3), (alarm: Alarm) => { this.BuildAlarmItem(alarm) }) } } .width('100%') } @Builder BuildAlarmItem(alarm: Alarm) { Row({ space: 15 }) { Column({ space: 5 }) { Text(this.formatAlarmTime(alarm.hour, alarm.minute)) .fontSize(20) .fontWeight(FontWeight.Bold) .fontColor('#FFFFFF') .alignSelf(ItemAlign.Start) Text(this.getAlarmDays(alarm.days)) .fontSize(12) .fontColor('#A0AEC0') .alignSelf(ItemAlign.Start) } .layoutWeight(1) Toggle({ type: ToggleType.Switch, isOn: alarm.enabled }) .onChange((value: boolean) => { alarm.enabled = value; }) .width(40) Button('删除') .onClick(() => { this.deleteAlarm(alarm.id); }) .backgroundColor('transparent') .fontColor('#FF6B6B') .fontSize(12) .padding(8) } .width('100%') .padding(15) .backgroundColor('#2D3748') .borderRadius(12) .margin({ bottom: 10 }) } @Builder BuildEmptyState(title: string, message: string) { Column({ space: 10 }) { Text('⏰') .fontSize(32) .opacity(0.5) Text(title) .fontSize(16) .fontColor('#A0AEC0') Text(message) .fontSize(14) .fontColor('#718096') } .width('100%') .height(100) .justifyContent(FlexAlign.Center) .backgroundColor('#2D3748') .borderRadius(12) } private startClock(): void { // 更新时间 setInterval(() => { this.currentTime = new Date(); this.updateWorldClocks(); this.checkAlarms(); if (this.isCountingDown && this.countdownTime > 0) { this.countdownTime--; if (this.countdownTime === 0) { this.countdownComplete(); } } }, 1000); } private updateWorldClocks(): void { const now = this.currentTime; this.worldClocks.forEach(clock => { const offset = this.getTimezoneOffset(clock.timezone); const cityTime = new Date(now.getTime() + offset * 60 * 60 * 1000); clock.time = this.formatTime(cityTime); }); } private getTimezoneOffset(timezone: string): number { // 简化的时区偏移计算 const offsets: { [key: string]: number } = { 'Asia/Shanghai': 8, 'America/New_York': -5, 'Europe/London': 0, 'Asia/Tokyo': 9 }; return offsets[timezone] || 0; } private formatTime(date: Date): string { const hours = date.getHours().toString().padStart(2, '0'); const minutes = date.getMinutes().toString().padStart(2, '0'); const seconds = date.getSeconds().toString().padStart(2, '0'); return `${hours}:${minutes}:${seconds}`; } private formatDate(date: Date): string { const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); const day = date.getDate().toString().padStart(2, '0'); return `${year}-${month}-${day}`; } private getWeekday(date: Date): string { const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; return weekdays[date.getDay()]; } private loadSampleAlarms(): void { this.alarms = [ { id: '1', hour: 7, minute: 30, days: [1, 2, 3, 4, 5], enabled: true }, { id: '2', hour: 9, minute: 0, days: [0, 6], enabled: false }, { id: '3', hour: 22, minute: 0, days: [0, 1, 2, 3, 4, 5, 6], enabled: true } ]; } private formatAlarmTime(hour: number, minute: number): string { return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`; } private getAlarmDays(days: number[]): string { if (days.length === 7) return '每天'; if (days.length === 5 && !days.includes(0) && !days.includes(6)) return '工作日'; if (days.length === 2 && days.includes(0) && days.includes(6)) return '周末'; const dayNames = ['日', '一', '二', '三', '四', '五', '六']; return days.map(day => dayNames[day]).join(', '); } private showAlarmDialog(): void { // 模拟显示闹钟设置对话框 console.log('显示闹钟设置对话框'); // 这里可以添加新的闹钟 const newAlarm: Alarm = { id: Date.now().toString(), hour: 8, minute: 0, days: [1, 2, 3, 4, 5], enabled: true }; this.alarms.push(newAlarm); } private deleteAlarm(id: string): void { this.alarms = this.alarms.filter(alarm => alarm.id !== id); } private startCountdown(seconds: number): void { if (this.isCountingDown) { this.isCountingDown = false; this.countdownTime = 0; } else { this.isCountingDown = true; this.countdownTime = seconds; } } private countdownComplete(): void { this.isCountingDown = false; // 模拟倒计时完成提醒 console.log('倒计时完成!'); } private startStopwatch(): void { // 模拟秒表功能 console.log('启动秒表'); } private checkAlarms(): void { const now = this.currentTime; const currentHour = now.getHours(); const currentMinute = now.getMinutes(); const currentDay = now.getDay(); this.alarms.forEach(alarm => { if (alarm.enabled && alarm.hour === currentHour && alarm.minute === currentMinute && alarm.days.includes(currentDay)) { this.triggerAlarm(alarm); } }); } private triggerAlarm(alarm: Alarm): void { // 模拟闹钟触发 console.log(`闹钟触发: ${this.formatAlarmTime(alarm.hour, alarm.minute)}`); // 这里可以添加声音或震动提醒 } } class Alarm { id: string = ''; hour: number = 0; minute: number = 0; days: number[] = []; enabled: boolean = true; } class WorldClock { city: string = ''; timezone: string = ''; time: string = ''; }

想入门鸿蒙开发又怕花冤枉钱?别错过!现在能免费系统学 -- 从 ArkTS 面向对象核心的类和对象、继承多态,到吃透鸿蒙开发关键技能,还能冲刺鸿蒙基础 +高级开发者证书,更惊喜的是考证成功还送好礼!快加入我的鸿蒙班,一起从入门到精通,班级链接:点击https://developer.huawei.com/consumer/cn/training/classDetail/b7365031334e4353a9a0fd6785bb0791?type=1?ha_source=hmosclass&ha_sourceId=89000248免费进入

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!