服装网站策划设计北京工商网站

当前位置: 首页 > news >正文

服装网站策划设计,北京工商网站,无锡网站优化,一个网站开发的流程敲木鱼是一款具有禅意的趣味小游戏#xff0c;本文将通过鸿蒙 ArkUI 框架的实现代码#xff0c;逐步解析其核心技术点#xff0c;包括动画驱动、状态管理、音效震动反馈等。 一、架构设计与工程搭建 1.1 项目结构解析 完整项目包含以下核心模块#xff1a; ├── entry…敲木鱼是一款具有禅意的趣味小游戏本文将通过鸿蒙 ArkUI 框架的实现代码逐步解析其核心技术点包括动画驱动、状态管理、音效震动反馈等。 一、架构设计与工程搭建 1.1 项目结构解析 完整项目包含以下核心模块 ├── entry/src/main/ets/ │ ├── components/ // 自定义组件库 │ ├── model/ // 数据模型如StateArray │ ├── pages/ // 页面组件WoodenFishGame.ets │ └── resources/ // 多媒体资源木鱼图标、音效 通过模块化设计分离 UI层pages、逻辑层model、资源层resources符合鸿蒙应用开发规范。 1.2 组件化开发模式 使用 Component 装饰器创建独立可复用的 UI 单元Entry 标记为页面入口。关键状态通过 State 管理 Entry Component struct WoodenFishGame {State count: number 0; // 功德计数器State scaleWood: number 1; // 木鱼缩放系数State rotateWood: number 0; // 木鱼旋转角度State animateTexts: ArrayStateArray []; // 动画队列private audioPlayer?: media.AVPlayer; // 音频播放器实例private autoPlay: boolean false; // 自动敲击标志位 } State 实现了 响应式编程当变量值变化时ArkUI 自动触发关联 UI 的重新渲染。 二、动画系统深度解析 2.1 木鱼敲击复合动画 动画分为 按压收缩100ms和 弹性恢复200ms两个阶段通过 animateTo 实现平滑过渡 playAnimation() {// 第一阶段快速收缩左旋animateTo({duration: 100, curve: Curve.Friction // 摩擦曲线模拟物理阻力}, () {this.scaleWood 0.9; // X/Y轴缩放到90%this.rotateWood -2; // 逆时针旋转2度});// 第二阶段弹性恢复setTimeout(() {animateTo({duration: 200,curve: Curve.Linear // 线性恢复保证流畅性}, () {this.scaleWood 1; this.rotateWood 0;});}, 100); // 延迟100ms衔接动画 } 曲线选择 Curve.Friction 模拟木槌敲击时的瞬间阻力Curve.Linear 确保恢复过程无加速度干扰 2.2 功德文字飘浮动画 采用 动态数组管理 唯一ID标识 实现多实例独立控制 countAnimation() {const animId new Date().getTime(); // 时间戳生成唯一ID// 添加新动画元素this.animateTexts […this.animateTexts, { id: animId, opacity: 1, offsetY: 20 }];// 启动渐隐上移动画animateTo({duration: 800,curve: Curve.EaseOut // 缓出效果模拟惯性}, () {this.animateTexts this.animateTexts.map(item item.id animId ? { …item, opacity: 0, offsetY: -100 } : item);});// 动画完成后清理内存setTimeout(() {this.animateTexts this.animateTexts.filter(t t.id ! animId);}, 800); // 与动画时长严格同步 } 关键技术点 数据驱动通过修改 animateTexts 数组触发 ForEach 重新渲染分层动画opacity 控制透明度offsetY 控制垂直位移内存优化定时清理已完成动画元素防止数组膨胀 三、多模态交互实现 3.1 触觉震动反馈 调用 kit.SensorServiceKit 的振动模块实现触觉反馈 vibrator.startVibration({type: time, // 按时间模式振动duration: 50 // 50ms短震动 }, {id: 0, // 振动器IDusage: alarm // 资源使用场景标识 }); 参数调优建议 时长50ms 短震动模拟木鱼敲击的“清脆感”强度鸿蒙系统自动根据 usage 分配最佳强度等级 3.2 音频播放与资源管理 通过 media.AVPlayer 实现音效播放 aboutToAppear(): void {media.createAVPlayer().then(player {this.audioPlayer player;this.audioPlayer.url ; this.audioPlayer.loop false; // 禁用循环播放}); }// 敲击时重置播放进度 if (this.audioPlayer) {this.audioPlayer.seek(0); // 定位到0毫秒this.audioPlayer.play(); // 播放音效 } 最佳实践 预加载资源在 aboutToAppear 阶段提前初始化播放器避免延迟调用 seek(0) 确保每次点击即时发声资源释放需在 onPageHide 中调用 release() 防止内存泄漏 四、自动敲击功能实现 4.1 定时器与状态联动 通过 Toggle 组件切换自动敲击模式 // 状态切换回调 Toggle({ type: ToggleType.Checkbox, isOn: false }).onChange((isOn: boolean) {this.autoPlay isOn;if (isOn) {this.startAutoPlay();} else {clearInterval(this.intervalId); // 清除指定定时器}});// 启动定时器 private intervalId: number 0; startAutoPlay() {this.intervalId setInterval(() {if (this.autoPlay) this.handleTap();}, 400); // 400ms间隔模拟人类点击频率 } 关键改进点 使用 intervalId 保存定时器引用避免 clearInterval() 失效间隔时间 400ms 平衡流畅度与性能消耗 4.2 线程安全与性能保障 风险点频繁的定时器触发可能导致 UI 线程阻塞 解决方案 // 在 aboutToDisappear 中清除定时器 aboutToDisappear() {clearInterval(this.intervalId); } 确保页面隐藏时释放资源避免后台线程持续运行。 五、UI 布局与渲染优化 5.1 层叠布局与动画合成 使用 Stack 实现多层 UI 元素的叠加渲染 Stack() {// 木鱼主体底层Image(\(r(app.media.icon_wooden_fish)).width(280).height(280).margin({ top: -10 }).scale({ x: this.scaleWood, y: this.scaleWood }).rotate({ angle: this.rotateWood });// 功德文字上层ForEach(this.animateTexts, (item, index) {Text(1).translate({ y: -item.offsetY * index }) // 按索引错位显示}); } 渲染优化技巧 为静态图片资源添加 fixedSize(true) 避免重复计算使用 translate 代替 margin 实现位移减少布局重排 5.2 状态到 UI 的高效绑定 通过 链式调用 实现样式动态绑定 Text(功德 \){this.count}).fontSize(20).fontColor(#4A4A4A).margin({ top: 20 AppUtil.getStatusBarHeight() // 动态适配刘海屏}) 适配方案 AppUtil.getStatusBarHeight() 获取状态栏高度避免顶部遮挡使用鸿蒙的 弹性布局Flex自动适应不同屏幕尺寸 六、完整代码 import { media } from kit.MediaKit; import { vibrator } from kit.SensorServiceKit; import { AppUtil, ToastUtil } from pura/harmony-utils; import { StateArray } from ../model/HomeModel;Entry Component struct WoodenFishGame {State count: number 0;State scaleWood: number 1;State rotateWood: number 0;audioPlayer?: media.AVPlayer;// 添加自动敲击功能autoPlay: boolean false;// 新增状态变量State animateTexts: ArrayStateArray []aboutToAppear(): void {media.createAVPlayer().then(player {this.audioPlayer playerthis.audioPlayer.url })}startAutoPlay() {setInterval(() {if (this.autoPlay) {this.handleTap();}}, 400);}// 敲击动画playAnimation() {animateTo({duration: 100,curve: Curve.Friction}, () {this.scaleWood 0.9;this.rotateWood -2;});setTimeout(() {animateTo({duration: 200,curve: Curve.Linear}, () {this.scaleWood 1;this.rotateWood 0;});}, 100);}// 敲击处理handleTap() {this.count;this.playAnimation();this.countAnimation();// 在handleTap中添加vibrator.startVibration({type: time,duration: 50}, {id: 0,usage: alarm});// 播放音效if (this.audioPlayer) {this.audioPlayer.seek(0);this.audioPlayer.play();}}countAnimation(){// 生成唯一ID防止动画冲突const animId new Date().getTime()// 初始化动画状态this.animateTexts […this.animateTexts, {id: animId, opacity: 1, offsetY: 20}]// 执行动画animateTo({duration: 800,curve: Curve.EaseOut}, () {this.animateTexts this.animateTexts.map(item {if (item.id animId) {return { id:item.id, opacity: 0, offsetY: -100 }}return item})})// 动画完成后清理setTimeout(() {this.animateTexts this.animateTexts.filter(t t.id ! animId)}, 800)}build() {Column() {// 计数显示Text(功德 \({this.count}).fontSize(20).margin({ top: 20AppUtil.getStatusBarHeight() })// 木鱼主体Stack() {// 可敲击部位Image(\)r(app.media.icon_wooden_fish)).width(280).height(280).margin({ top: -10 }).scale({ x: this.scaleWood, y: this.scaleWood }).rotate({ angle: this.rotateWood }).onClick(() this.handleTap())// 功德文字动画容器ForEach(this.animateTexts, (item:StateArray,index) {Text(1).fontSize(24).fontColor(#FFD700).opacity(item.opacity).margin({ top: -100}) // 初始位置调整.translate({ y: -item.offsetY*index }) // 使用translateY实现位移.animation({ duration: 800, curve: Curve.EaseOut })})}.margin({ top: 50 })Row(){// 自动敲击开关扩展功能Toggle({ type: ToggleType.Checkbox, isOn: false }).onChange((isOn: boolean) {// 可扩展自动敲击功能this.autoPlay isOn;if (isOn) {this.startAutoPlay();} else {clearInterval();}})Text(自动敲击)}.alignItems(VerticalAlign.Center).justifyContent(FlexAlign.Center).width(100%).position({bottom:100})}.width(100%).height(100%).backgroundColor(#f0f0f0)} }