【OpenHarmony/HarmonyOs 】声音传播实验:介质切换、波纹动画与本地物理计算
【OpenHarmony/HarmonyOs 】声音传播实验介质切换、波纹动画与本地物理计算本文基于我的 OpenHarmony/HarmonyOS 项目「物理视界 PhysicsVision」整理。项目中的「声音的传播」模型支持空气、水、钢铁三种介质切换通过 Canvas 波纹动画展示声波传播速度和波长变化。这一篇对应“沉浸式交互体验”和“端侧 AI/端侧计算”的主题重点讲如何用本地计算完成教学可视化。一、声音传播为什么适合做成互动实验声音是机械波需要介质才能传播。学生在学习时经常会背结论空气中声速约 340m/s水中声速约 1500m/s钢铁中声速约 5100m/s。但如果只是背数字很难理解“介质不同传播速度不同”这个现象。所以项目把声音传播做成动画选择不同介质后波纹扩散速度和数据面板都会变化。二、核心状态频率、介质、播放状态页面中定义Statefrequency: number 2Statemedium: number 0StateisPlaying: boolean falseStatetime: number 0其中frequency表示频率medium表示当前介质isPlaying控制动画播放time控制波纹扩散。这些状态共同决定 Canvas 中的波纹画面。三、介质数据名称、速度和颜色项目把三种介质配置成数组privatemediumNames:string[] [空气,水,钢铁]privatemediumSpeeds:number[] [340,1500,5100]privatemediumColors:string[] [#E8F4FD,#B3E5FC,#CFD8DC]这是一种简单但很实用的结构。介质不仅影响数值也影响背景颜色空气浅蓝水更明显的蓝钢铁灰蓝。视觉和物理含义形成对应学生更容易记住。四、声速和波长计算声速由当前介质决定getSpeed(): number {returnthis.mediumSpeeds[this.medium] }波长由公式计算getWavelength(): number {returnthis.getSpeed() /this.frequency }这对应物理公式λv / f这里完全是本地计算不需要网络也不涉及任何敏感权限。五、动画播放定时更新 time播放逻辑如下startAnimation(): void {if(this.timerId ! -1)returnthis.isPlaying truethis.time 0this.timerId setInterval(() {this.time 0.03if(this.canvasReady)this.drawScene() },16) }每 16ms 更新一次时间并重绘。声波传播的“动感”来自time不断变化。页面退出时清理aboutToDisappear(): void {if(this.timerId ! -1) { clearInterval(this.timerId)this.timerId -1} }这是所有动画页面都应该做的资源管理。六、绘制声源Canvas 中先绘制声源letcx:number60letcy:number h /2ctx.fillStyle #FF6D00ctx.strokeStyle this.wireColor() ctx.lineWidth3ctx.beginPath() ctx.arc(cx, cy,16,0, Math.PI *2) ctx.fill() ctx.stroke() ctx.fillStyle #FFFFFFctx.font bold14px sans-serif ctx.textAlign center ctx.fillText(, cx, cy 5)声源固定在左侧波纹从左向右扩散。这种布局很直观适合手机竖屏阅读。七、绘制波纹速度影响扩散波纹绘制核心如下letspeedFactor:numberthis.getSpeed() /340letmaxRadius:number w - cxletwaveSpacing:number30/this.frequencyfor(leti 1; i 15; i) {letradius:number (i * waveSpacing this.time* speedFactor *40) % maxRadiusif(radius 20)continueletalpha:number1- radius / maxRadiusif(alpha 0.05)continuectx.strokeStylergba(45, 52, 54,${alpha *0.6})ctx.lineWidth2ctx.beginPath() ctx.arc(cx, cy, radius, -Math.PI/3,Math.PI/3) ctx.stroke() }这里有两个关键变量speedFactor介质越快波纹扩散越快waveSpacing频率越高波纹间距越小。这正好把声速、频率、波长三者关系可视化。八、介质切换按钮页面中提供空气、水、钢铁三个按钮Button(️ 空气).backgroundColor(this.medium 0 ? #1A73E8 : $r(app.color.bg_card)) .onClick(() { this.medium 0})Button( 水).backgroundColor(this.medium 1 ? #1A73E8 : $r(app.color.bg_card)) .onClick(() { this.medium 1})Button( 钢铁).backgroundColor(this.medium 2 ? #1A73E8 : $r(app.color.bg_card)) .onClick(() { this.medium 2})这里没有做复杂选择器而是直接用按钮。因为介质数量少按钮比下拉菜单更直观。九、隐私角度不需要录音权限一个容易误解的点是声音传播模型并不需要麦克风。项目不是采集真实声音而是通过公式和 Canvas 模拟声波传播。这非常符合隐私保护主题不申请麦克风不录音不上传音频不做声纹识别不依赖 AI 识别。学生仍然能理解声音传播但不会暴露任何声音数据。十、总结声音传播模型展示了教育应用的一种好方向用本地公式和可视化动画替代敏感数据采集。这篇文章对应的主题是沉浸式交互体验 端侧计算 隐私保护。项目通过介质切换、波纹动画、速度和波长计算把一个抽象知识点变成了可以操作的实验。