打造自己的中秋 AR 赏月应用:实现虚实融合的节日体验
中秋佳节,赏月、品茗、话家常是传统习俗。随着增强现实(AR)技术的发展,我们可以用鸿蒙的开发能力,打造一款 “AR 中秋赏月” 应用 —— 让虚拟玉兔在现实场景中跳跃,让数字月饼 “飘落” 在桌面,甚至能通过 AR 扫描月亮触发专属节日特效。这里我将将带大家从技术选型到代码实现,完整搭建这款充满节日氛围的鸿蒙 T应用。
文章目录
- 一、应用核心功能与技术栈
- 1. 核心功能规划
- 2. 技术栈依赖
- 二、前置准备:环境配置与资源准备
- 1. 开发环境配置
- 2. 中秋 AR 资源准备
- 三、核心代码实现:从 AR 场景初始化到互动功能
- 1. AR 场景初始化:连接 AR Engine 与相机
- 2. 虚拟元素叠加:3D 模型与 AR 场景融合
- 3. 互动与分享功能:截图保存与社交分享
- 四、开发注意事项与优化方向
- 1. 性能优化
- 2. 兼容性适配
- 3. 用户体验优化
- 五、总结

一、应用核心功能与技术栈
在开始开发前,我们先明确应用的核心场景与依赖技术,确保开发方向清晰:
1. 核心功能规划
AR 场景识别:通过鸿蒙 AR Engine 识别现实中的 “天空区域”,将虚拟月亮模型叠加到真实天空中,实现 “虚实赏月” 效果;
节日互动特效:点击虚拟月亮触发玉兔跳跃、月饼飘落动画,支持手势缩放调整虚拟元素大小;
节日祝福分享:将 AR 赏月画面截图,生成带中秋文案的海报,支持分享到社交平台;
设备兼容性适配:适配鸿蒙手机、平板等不同尺寸设备,保证 AR 场景显示正常。
2. 技术栈依赖
基础框架:HarmonyOS Stage 模型(API 9+),TypeScript 作为开发语言;
AR 能力:依赖鸿蒙 AR Engine(@ohos.arengine),实现环境跟踪、平面识别、虚实叠加;
图形渲染:使用鸿蒙 ArkUI 的 3D 组件()加载 GLB 格式的中秋模型(月亮、玉兔、月饼);
权节日氛围的鸿蒙 TS 应用。
二、前置准备:环境配置与资源准备
在写代码前,我们需要完成两项关键准备工作,避免开发中出现环境或资源问题:
1. 开发环境配置
DevEco Studio 版本:需升级到 4.0 及以上,确保支持 API 9 + 的 AR Engine 能力;
AR Engine 依赖引入:在package.json中添加 AR Engine 依赖,或通过 DevEco Studio 的 “项目设置 - 模块设置” 手动引入:
"dependencies": {"@ohos.arengine": "^1.0.0","@ohos.arkui.3d": "^1.0.0"
}权限声明:在module.json5中声明必要权限,AR 场景核心依赖相机权限,分享功能依赖存储权限:
"reqPermissions": [{"name": "ohos.permission.CAMERA","reason": "需要相机采集现实场景,实现AR赏月效果","usedScene": { "abilities": ["MainAbility"], "when": "inuse" }},{"name": "ohos.permission.WRITE_MEDIA","reason": "需要保存AR赏月截图,用于节日分享","usedScene": { "abilities": ["MainAbility"], "when": "inuse" }}
]
2. 中秋 AR 资源准备
3D 模型:准备 GLB 格式的中秋相关模型,推荐从Sketchfab下载开源模型(需注意版权),如:
低多边形风格月亮模型(带光晕效果);
动态玉兔模型(含跳跃、捣药动画);
圆形月饼模型(带纹理贴图);
特效资源:准备粒子特效配置文件(如月饼飘落的粒子参数),用于增强节日氛围。
三、核心代码实现:从 AR 场景初始化到互动功能
接下来,我们分模块实现应用的核心功能,重点讲解 AR 场景搭建、虚拟元素叠加、互动逻辑三个关键部分。
1. AR 场景初始化:连接 AR Engine 与相机
首先需要初始化 AR Engine,建立相机采集与 AR 跟踪的关联,这是实现虚实融合的基础。我们在MainPage.ets中编写初始化逻辑:
import arengine from '@ohos.arengine';
import camera from '@ohos.multimedia.camera';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import { BusinessError } from '@ohos.base';@Entry
@Component
struct ARMidAutumnPage {// AR Engine核心对象private arSession: arengine.ARSession | null = null;// 相机预览组件控制器private cameraPreviewCtrl: CameraPreviewController = new CameraPreviewController();// 是否初始化成功@State isInitSuccess: boolean = false;build() {Column() {// 相机预览(作为AR场景的现实背景)CameraPreview(controller: this.cameraPreviewCtrl).width('100%').height('100%')// 叠加3D虚拟元素(月亮、玉兔等).overlay(() => {if (this.isInitSuccess) {AR3DElements() // 后续实现3D元素组件}})}.onPageShow(() => {this.initARSession(); // 页面显示时初始化AR}).onPageHide(() => {this.destroyARSession(); // 页面隐藏时销毁AR资源})}// 初始化AR Session与相机private async initARSession() {try {// 1. 检查并申请相机权限const hasCameraPerm = await this.checkAndRequestPermission('ohos.permission.CAMERA');if (!hasCameraPerm) {promptAction.showToast({ message: '请授予相机权限以使用AR功能' });return;}// 2. 创建AR Sessionthis.arSession = await arengine.createARSession();// 3. 配置AR场景:启用环境跟踪(识别天空、平面)const config = await this.arSession.getConfig();config.enableEnvironmentTracking(true); // 开启环境跟踪await this.arSession.configure(config);// 4. 绑定相机:将AR Session与相机预览关联const cameraManager = camera.getCameraManager();const cameraDevice = await cameraManager.getCameraDevices()[0]; // 获取默认相机await this.arSession.bindCamera(cameraDevice);// 5. 启动AR Sessionawait this.arSession.resume();this.isInitSuccess = true;console.log('AR场景初始化成功,可开始AR赏月');} catch (err) {console.error(`AR初始化失败:${(err as BusinessError).message}`);this.isInitSuccess = false;}}// 检查并申请权限private async checkAndRequestPermission(permName: string): Promise<boolean> {const atManager = abilityAccessCtrl.createAtManager();const tokenId = abilityAccessCtrl.getTokenId();try {const status = await atManager.checkPermission(tokenId, permName);if (status === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {return true;}// 申请权限const result = await atManager.requestPermissionsFromUser(tokenId, [permName]);return result.authResults[0] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED;} catch (err) {console.error(`权限处理失败:${(err as BusinessError).message}`);return false;}}// 销毁AR Session,释放资源private async destroyARSession() {if (this.arSession) {await this.arSession.pause();await this.arSession.destroy();this.arSession = null;this.isInitSuccess = false;}}
}
2. 虚拟元素叠加:3D 模型与 AR 场景融合
AR 场景初始化成功后,需要将中秋 3D 模型(月亮、玉兔)叠加到现实场景中。这里我们使用 ArkUI 的 3D 组件,结合 AR Engine 的环境跟踪数据,确保虚拟元素 “锚定” 在现实空间中(如将月亮固定在天空区域)。
创建AR3DElements.ets组件,实现 3D 模型加载与位置校准:
import { Ark3D, Model, ModelLoader, Vector3 } from '@ohos.arkui.3d';
import arengine from '@ohos.arengine';@Component
struct AR3DElements {// AR Session从父组件传递@Prop arSession: arengine.ARSession | null;// 月亮模型加载器private moonModelLoader: ModelLoader = new ModelLoader();// 玉兔模型加载器private rabbitModelLoader: ModelLoader = new ModelLoader();// 虚拟元素位置(初始设为天空区域)@State moonPosition: Vector3 = new Vector3(0, 2, -5); // x:水平, y:高度, z:距离@State rabbitPosition: Vector3 = new Vector3(-1, 1.8, -5);build() {Ark3D().width('100%').height('100%').onReady(() => {this.loadModels(); // ARK3D就绪后加载模型this.trackSkyArea(); // 跟踪天空区域,校准月亮位置}).children([// 月亮模型Model(loader: this.moonModelLoader).position(this.moonPosition).scale(0.5, 0.5, 0.5) // 缩放模型大小.onClick(() => {this.triggerMoonEffect(); // 点击月亮触发特效}),// 玉兔模型Model(loader: this.rabbitModelLoader).position(this.rabbitPosition).scale(0.3, 0.3, 0.3).animation('jump', true) // 自动播放跳跃动画])}// 加载3D模型(GLB格式)private async loadModels() {try {// 加载月亮模型(路径需与项目资源目录对应)await this.moonModelLoader.load('assets/models/moon.glb');// 加载玉兔模型await this.rabbitModelLoader.load('assets/models/rabbit.glb');console.log('中秋3D模型加载成功');} catch (err) {console.error(`模型加载失败:${(err as BusinessError).message}`);}}// 跟踪天空区域,校准月亮位置(确保月亮显示在真实天空中)private async trackSkyArea() {if (!this.arSession) return;// 循环获取AR环境跟踪数据setInterval(async () => {try {const frame = await this.arSession.updateFrame(); // 获取AR帧数据const trackables = await frame.getTrackables(arengine.TrackableType.PLANE); // 获取平面跟踪结果for (const trackable of trackables) {const plane = trackable as arengine.ARPlane;// 判断是否为“天空平面”(AR Engine会识别天空为特殊平面)if (plane.getPlaneType() === arengine.ARPlane.PlaneType.SKY) {const centerPose = await plane.getCenterPose(); // 获取天空平面中心姿态// 根据天空平面位置调整月亮位置,确保虚拟月亮与真实天空对齐this.moonPosition = new Vector3(centerPose.getTranslationX(),centerPose.getTranslationY() + 1, // 向上偏移1单位,避免与天空平面重叠centerPose.getTranslationZ() - 2 // 向前偏移2单位,让月亮更“靠前”);break;}}} catch (err) {console.error(`天空跟踪失败:${(err as BusinessError).message}`);}}, 100); // 每100ms更新一次位置,确保实时对齐}// 点击月亮触发特效(玉兔跳跃、月饼飘落)private triggerMoonEffect() {// 1. 玉兔跳跃动画加速this.rabbitModelLoader.setAnimationSpeed('jump', 2); // 动画速度加倍// 2. 触发月饼飘落粒子特效(此处简化,实际需结合粒子组件实现)promptAction.showToast({ message: '中秋快乐!月饼来啦~' });// 3. 1秒后恢复玉兔动画速度setTimeout(() => {this.rabbitModelLoader.setAnimationSpeed('jump', 1);}, 1000);}
}
3. 互动与分享功能:截图保存与社交分享
最后,我们为应用添加 “截图分享” 功能,让用户能将 AR 赏月画面保存并分享给亲友。在MainPage.ets中添加分享按钮,并实现截图逻辑:
// 在MainPage.ets的build方法中添加分享按钮
Column() {// 相机预览与AR元素(原有代码)// ...// 分享按钮(固定在底部)Button('保存AR赏月画面').width(200).height(40).backgroundColor('#FF4500').textStyle({ color: 'white' }).margin({ bottom: 30 }).onClick(() => {this.captureARScreen(); // 点击触发截图})
}// 截图并保存到相册
private async captureARScreen() {try {// 1. 检查存储权限const hasStoragePerm = await this.checkAndRequestPermission('ohos.permission.WRITE_MEDIA');if (!hasStoragePerm) {promptAction.showToast({ message: '请授予存储权限以保存截图' });return;}// 2. 对相机预览+AR元素区域截图(使用鸿蒙截图API)const pixelMap = await capturePixelMap(this.cameraPreviewCtrl); // 简化写法,实际需通过组件ID定位// 3. 保存截图到相册const mediaLibrary = media.createMediaLibrary();const savePath = `Pictures/ARMidAutumn/${new Date().getTime()}.png`;const saveResult = await mediaLibrary.saveImageToAlbum(pixelMap, savePath);if (saveResult) {promptAction.showToast({ message: `截图已保存到:${savePath}` });// 4. 可选:调用分享API,直接分享截图(需引入分享模块)// await shareImage(savePath);} else {promptAction.showToast({ message: '截图保存失败' });}} catch (err) {console.error(`截图失败:${(err as BusinessError).message}`);}
}
四、开发注意事项与优化方向
在实际开发中,还需要关注以下问题,确保应用体验流畅、稳定:
1. 性能优化
模型轻量化:中秋 3D 模型需控制面数(建议单个模型面数 < 10000),避免设备卡顿;
AR 帧率控制:通过arSession.setFrameRate(30)将 AR 帧速率设为 30fps,平衡性能与体验;
资源预加载:在应用启动时预加载 3D 模型,避免页面显示后加载导致的延迟。
2. 兼容性适配
设备支持:AR Engine 需设备支持 AR 功能(如具备陀螺仪、加速度计),可通过arSession.isSupported()判断设备兼容性;
屏幕适配:通过@ohos.device.screen获取屏幕尺寸,动态调整 3D 模型大小,避免在小屏设备上显示过大。
3. 用户体验优化
权限引导:当用户拒绝权限时,提供 “前往设置” 的跳转链接(通过abilityAccessCtrl.openPermissionSettings()实现);
加载提示:AR 初始化、模型加载时显示 “正在准备中秋 AR 场景…” 的加载动画,减少用户等待焦虑;
错误处理:当 AR Engine 初始化失败(如设备不支持),显示 “当前设备暂不支持 AR 功能,换个设备试试吧~” 的友好提示。
五、总结
ok,到这里就结束了。我们学习了如何结合鸿蒙 AR Engine 与 ArkUI 3D 能力,实现虚实融合的节日应用。从权限申请、AR 场景搭建,到 3D 模型叠加、互动功能实现,每一步都围绕 “技术赋能节日体验” 的核心,让传统中秋习俗与现代 AR 技术碰撞出有趣的火花。
后续我们还可以扩展更多功能,比如添加 “AR 中秋灯谜”(扫描特定图案触发灯谜)、“亲友 AR 同屏赏月”(通过分布式能力实现多设备同一场景互动)等,让应用更具趣味性和社交属性。最后祝大家中秋快乐,技术之路越走越宽!