用码道开发 HarmonyOS 7项目实现「锦绣中华·国庆献礼」互动案例
文章目录
前言
这次做的是一个 HarmonyOS 7 国庆主题应用。首页用祝福弹幕营造节日氛围,点击按钮进入贺卡页后,可以查看国庆倒计时、播放烟花动画,也可以通过摇一摇手机触发烟花。两台设备满足条件时,还能使用碰一碰分享祝福。
项目规模不大,但覆盖了 ArkUI 状态管理、页面路由、动画编排、加速度传感器和设备协同等能力。本文不罗列完整源码,只挑几个对实现和调试真正有帮助的片段展开说明。
项目结构与实现思路
页面代码位于:
entry/src/main/ets/pages/
├── Index.ets
└── Views/
└── NationalDayFestival.ets
两个页面各自负责一段完整体验:
| 页面 | 主要职责 |
|---|---|
Index.ets | 渐变背景、祝福弹幕和页面跳转 |
Views/NationalDayFestival.ets | 国庆倒计时、烟花粒子、触摸光效、传感器监听和碰一碰分享 |
项目使用 HarmonyOS 7 的 ArkTS 声明式 UI。页面中的动画开关、粒子位置和文案显隐都由 @State 驱动,再配合 animateTo 完成过渡。
这个案例没有一开始就拆出大量服务类。原因很简单:当前核心逻辑只服务于两个页面,过早分层反而会增加跳转成本。先把交互链路和生命周期处理清楚,后续能力继续增加时,再把传感器、分享和动画控制器独立出去更合适。
准备项目与开发素材
先创建 HarmonyOS 7 空项目,再把提示词、页面草图、功能清单和验收条件放进项目的素材目录。这样码道可以直接结合项目上下文工作,减少反复解释需求的次数。

准备好基础骨架后,将项目托管到代码平台,方便保留修改记录和回滚有问题的实现。

这里要注意,需求文档中的架构图表达的是预期模块关系,不代表源码里已经存在所有同名模块。检查实现时,应以当前页面文件、实际导入和调用链为准,避免出现“文档写了、代码却没有”的情况。
将码道安装到本地
码道既可以通过网页使用,也可以安装到本地。我的主要开发环境在本地,因此更习惯让它直接读取项目目录并配合编辑器完成修改。网页端界面如下:

在 macOS 终端中执行安装命令:
curl -fsSL https://raw.atomgit.com/atomgit_atomcode/atomcode/raw/main/scripts/install.sh | sh

不同操作系统的安装方式可能不同,本文使用的是 macOS。安装结束后,先检查版本号:
atomcode --version

能够正常输出版本号后,执行 atomcode 打开运行面板,再根据提示输入 /login 完成登录。

首页:祝福弹幕与页面路由
先看首页效果:

Index.ets 使用 ForEach 创建多条祝福弹幕。每条弹幕都有独立的行号、启动延迟、滚动时间和透明度,因此不会整齐地挤在同一条轨道上。
ForEach(IDX_DANMAKU, (item: IDanmaku, index: number) => {
IdxDanmakuItem({ item: item })
}, (item: IDanmaku, index: number) => index.toString())
弹幕组件内部通过 alive 标记判断页面是否仍然可见,避免组件退出后继续递归调度定时任务。弹幕层还设置了不参与命中测试,否则全屏弹幕容器可能会拦截底部按钮的点击事件。
点击“进入国庆贺卡”后,通过 router.pushUrl 跳转到主题页:
Button('进入国庆贺卡')
.onClick(() => {
this.btnGlow = !this.btnGlow;
router.pushUrl({ url: 'pages/Views/NationalDayFestival' });
})
路由代码本身很短,真正容易出错的是配置:页面路径、目录大小写和路由表必须保持一致。此类问题通常不会在编辑阶段直接暴露,而是运行后才表现为跳转失败,因此需要在预览器或真机上实际点击验证。
贺卡页:用状态编排烟花动画
贺卡页的烟花和祝福语消散效果如下:

NationalDayFestival.ets 没有把烟花做成一段不可控的连续动画,而是拆成几个可以独立修改的状态:
fireworksOn:决定是否渲染烟花层;fireScale:控制粒子向外扩散;fireFade:控制烟花余晖淡出;blessingOpacity:控制祝福语显隐;glowX、glowY:记录手指移动后的光斑位置。
触发烟花时,页面先生成粒子数据,再分阶段更新缩放和透明度。上一轮动画尚未结束时会直接返回,防止用户连续点击造成粒子叠加、定时任务堆积和明显掉帧。动画结束后再恢复初始状态,下一次触发就能从干净状态重新开始。
这种写法的价值在于可调试:如果某一段效果异常,可以分别检查粒子生成、扩散、淡出或祝福语浮层,而不是在一条长动画链里逐行排查。
处理国庆倒计时的日期边界
倒计时并不只是计算“今年 10 月 1 日减去今天”。如果当前日期已经过了国庆节,目标日期必须切换到下一年,否则页面会得到负数。JavaScript 的月份从 0 开始,所以 9 代表 10 月。
private computeDaysLeft(): void {
const now: Date = new Date();
const year: number = now.getMonth() > 8
? now.getFullYear() + 1
: now.getFullYear();
const target: Date = new Date(year, 9, 1, 0, 0, 0);
const diff: number = target.getTime() - now.getTime();
this.daysLeft = diff > 0 ? Math.ceil(diff / 86400000) : 0;
}
这里使用设备本地时间,适合节日展示类应用。若业务面向多个时区,或倒计时必须与服务器保持一致,就不能只依赖设备时间,需要统一时区和时间来源。
还有一个容易忽略的细节:这段逻辑在 10 月 1 日零点之后会直接计算下一年的国庆。如果产品希望国庆当天始终显示“0 天”或“今天”,需要单独增加当天判断,而不是照搬当前规则。
摇一摇触发烟花
为了让交互更自然,页面除了保留“点我放烟花”按钮,还监听了加速度传感器。回调中先计算三轴加速度的模长,再与重力基准比较;只有偏离超过阈值,并且与上一次触发间隔足够长,才会播放烟花。
sensor.on(sensor.SensorId.ACCELEROMETER, (data: sensor.AccelerometerResponse) => {
const magnitude: number = Math.sqrt(
data.x * data.x + data.y * data.y + data.z * data.z
);
const deviation: number = Math.abs(magnitude - ND_GRAVITY);
const now: number = Date.now();
if (deviation > ND_SHAKE_DEVIATION && now - this.lastShakeTs > ND_SHAKE_INTERVAL) {
this.lastShakeTs = now;
this.burstFireworks();
}
});
这里同时做了两层限制:
- 幅度阈值:过滤拿起手机、转动屏幕等普通动作;
- 时间去抖:避免一次连续摇动触发多轮烟花。
传感器阈值没有通用答案,不同设备的采样和用户握持方式都会影响结果。调试时不要只在模拟器中验证,应当在目标设备上多试几次,再调整 ND_SHAKE_DEVIATION 和 ND_SHAKE_INTERVAL。
按钮入口也不应删除。它既是传感器不可用时的降级方案,也方便开发阶段快速测试动画。页面退出时还要注销传感器监听,并清理仍在运行的定时器,否则返回页面后可能出现重复订阅和多次触发。
如何让码道更稳定地完成开发任务
与其一次性要求码道完成整个页面,更稳妥的方式是按可验收的功能拆分任务:
- 完成首页视觉效果、弹幕和路由;
- 完成倒计时和点击放烟花;
- 增加传感器监听、生命周期清理和碰一碰分享;
- 检查路由路径、状态复位以及真机兼容性。
提示词中最好同时写清项目路径、技术版本、素材位置和验收条件:
在 /xxxxxxx/entry 项目中完成以下需求:
1. 项目基于 HarmonyOS 7 和 ArkTS;
2. 需求说明和素材位于 /xxxxxx/物料;
3. 完成首页、贺卡页、倒计时和烟花交互;
4. 检查页面退出时的传感器和定时器清理;
5. 修改后说明涉及的文件和真机验证步骤。

第一轮编码结束后,不要只看“任务已完成”的回复,可以继续让码道按需求清单检查文件,并明确列出尚未验证的设备能力。传感器和碰一碰分享依赖真实设备环境,代码生成完成不等于功能已经验收。

碰一碰分享的使用前提
碰一碰分享效果如下:

两台设备都安装应用并满足系统能力条件时,可以通过碰一碰发送国庆祝福。发送端负责组装分享数据,接收端根据应用内约定处理内容。
接收端效果如下:

这类能力不能只验证“监听是否注册成功”,还要检查异常路径:目标设备未安装应用、系统能力未开启、分享中断或数据解析失败时,页面应该给出明确提示,而不是静默无响应。页面退出时同样要取消监听,避免重新进入页面后注册多次。
真机调试重点
传感器、碰一碰分享、动画时序和页面生命周期都依赖运行环境,真机阶段出现问题并不意外。反馈问题时,尽量同时提供:
- 可以稳定复现的操作步骤;
- 完整错误信息和错误码;
- 出问题的页面、函数或日志位置;
- 设备型号与系统版本;
- 预期行为和实际行为的差异。

不同设备和不同模型生成的实现可能存在差异。每次调整阈值、动画时间或生命周期逻辑后,都应该重新编译并在目标设备复测,不能只依据静态代码判断功能是否完成。
总结
这个案例表面上是一个节日主题页面,实际串联了 ArkUI 状态驱动、动画生命周期、日期边界、传感器去抖和设备协同。最值得保留的开发习惯有三个:先把需求拆成可以验收的小任务;为设备能力准备可操作的降级入口;任何涉及传感器和跨设备交互的功能,都以真机结果为准。
项目源码已开源,可通过以下地址查看:
更多推荐


所有评论(0)