##鸿蒙核心技术##运动开发##Media Kit(媒体服务)#

前言

在运动过程中,保持稳定的节奏对于提升运动效果至关重要。无论是跑步、骑自行车还是进行高强度间歇训练(HIIT),一个精准的节拍器都能帮助你更好地控制运动节奏,从而达到更好的锻炼效果。本文将结合鸿蒙(HarmonyOS)开发实战经验,深入解析如何开发一个运动节拍器,让你在运动中也能轻松掌握节奏。

一、为什么选择 SoundPool 而不是 AVPlayer

在开发运动节拍器时,我们选择了SoundPool而不是AVPlayer。这是因为SoundPool在播放短促的提示音时表现更为出色,能够快速响应并确保音效的及时播放,这对于需要精确控制节奏的运动节拍器来说至关重要。而AVPlayer更适合用于播放长音频文件,如音乐或视频,其响应速度和音效播放的即时性不如SoundPool

二、运动节拍器的核心逻辑

1.初始化音效

在节拍器启动前,我们需要加载音效文件并初始化SoundPool。以下是初始化音效的核心代码:

async initSound() {
this.soundPool = await media.createSoundPool(1, {
usage: audio.StreamUsage.STREAM_USAGE_MUSIC, // 音频流使用类型:音乐
rendererFlags: 1
}); const context = getContext(this) as common.UIAbilityContext;
const fd = context.resourceManager.getRawFdSync('medias/metronome2.mp3'); // 建议使用短促"嘀"声
this.soundId = await this.soundPool.load(
fd.fd,
fd.offset,
fd.length
);
}

2.节拍器播放逻辑

节拍器的核心逻辑是根据设置的 BPM(每分钟节拍数)定时播放音效,并在每次播放时触发视觉提示(如闪光)。以下是节拍器播放逻辑的核心代码:

startMetronome() {
if (this.isPlaying) return; this.isPlaying = true;
const interval = 60000 / this.bpm; // 节拍间隔 const playWithFlash = () => {
this.flashActive = true;
setTimeout(() => this.flashActive = false, 100); // 在 100 毫秒后将 flashActive 设置为 false,恢复视觉状态。 if (this.soundPool && this.soundId !== -1) {
this.soundPool.play(this.soundId, {
loop: 0,
rate: 1.0,
leftVolume: 1.0, // 最大音量确保运动时能听见
rightVolume: 1.0,
priority: 0
});
} this.timerId = setTimeout(playWithFlash, interval);
}; playWithFlash();
}

3.停止节拍器

停止节拍器时,我们需要清除定时器并释放SoundPool资源。以下是停止节拍器的核心代码:

stopMetronome() {
this.isPlaying = false;
clearTimeout(this.timerId);
}

三、用户界面设计

为了让用户能够方便地控制节拍器,我们需要设计一个简洁直观的用户界面。以下是用户界面的核心代码:

build() {
Column() {
// 大号视觉提示区
Circle()
.width(200)
.height(200)
.fill(this.flashActive ? Color.Red : Color.White)
.margin({ bottom: 40 })
.animation({ duration: 50, curve: Curve.EaseIn }) // 超大 BPM 显示
Text(`${this.bpm}`)
.fontSize(60)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 30 }) // 运动专用 BPM 范围滑块
Slider({
value: this.bpm,
min: 40, // 最低有效运动节奏
max: 200, // 高强度间歇训练上限
step: 1
})
.width('90%')
.height(60)
.onChange((value: number) => {
this.bpm = value;
if (this.isPlaying) {
this.stopMetronome();
this.startMetronome();
}
}) // 运动场景专用控制按钮
Button(this.isPlaying ? '停止运动' : '开始运动')
.width(200)
.height(80)
.fontSize(24)
.backgroundColor(this.isPlaying ? Color.Red : Color.Green)
.onClick(() => {
this.isPlaying ? this.stopMetronome() : this.startMetronome();
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}

核心点解析

• 视觉提示:通过Circle组件和flashActive状态,实现视觉上的节拍提示。

• BPM 显示:通过Text组件显示当前的 BPM 值,让用户能够直观地看到节拍频率。

• BPM 调整:通过Slider组件允许用户调整 BPM 值,并在调整后自动更新节拍器频率。

• 控制按钮:通过Button组件实现节拍器的启动和停止功能。

四、优化与改进

1.根据运动步频设置节拍器频率

为了更好地适应用户的运动节奏,我们可以根据用户的步频动态调整节拍器的频率。我之前的文章中有如何获取步频步幅。

private async updateBpmFromStepFrequency() {
// 获取当前步频
const currentStepFrequency = await this.getStepFrequency();
this.bpm = Math.round(currentStepFrequency * 60); // 将步频转换为 BPM
if (this.isPlaying) {
this.stopMetronome();
this.startMetronome();
}
}

2.增加音效选择功能

为了满足不同用户的需求,可以增加音效选择功能,允许用户选择不同的提示音。例如,提供多种音效文件供用户选择。

private soundOptions: string[] = ['metronome1.mp3', 'metronome2.mp3', 'metronome3.mp3'];
private selectedSoundIndex: number = 0; private async loadSound() {
const context = getContext(this) as common.UIAbilityContext;
const fd = context.resourceManager.getRawFdSync(`medias/${this.soundOptions[this.selectedSoundIndex]}`);
this.soundId = await this.soundPool.load(
fd.fd,
fd.offset,
fd.length
);
}

3.优化视觉提示效果

为了提升用户体验,可以进一步优化视觉提示效果,例如增加动画效果或改变提示颜色。

Circle()
.width(200)
.height(200)
.fill(this.flashActive ? Color.Red : Color.White)
.margin({ bottom: 40 })
.animation({ duration: 100, curve: Curve.EaseInOut }) // 增加动画效果

五、总结

通过鸿蒙的SoundPool和相关 API,我们可以轻松开发一个功能强大的运动节拍器。

HarmonyOS运动开发:打造你的专属运动节拍器的更多相关文章

  1. 乘风破浪,遇见华为鸿蒙智能终端系统(HarmonyOS 2),打造面向全场景的分布式操作系统

    什么是鸿蒙智能终端系统(HarmonyOS 2) HarmonyOS 是新一代的智能终端操作系统,为不同设备的智能化.互联与协同提供了统一的语言.带来简洁,流畅,连续,安全可靠的全场景交互体验. ht ...

  2. 鸿蒙HarmonyOS应用开发落地实践,Harmony Go 技术沙龙落地北京

    12月26日,华为消费者BG软件部开源中心与51CTO Harmony OS技术社区携手,共同主办了主题为"Harmony OS 应用开发落地实践"的 Harmony Go 技术沙 ...

  3. javascript运动系列第八篇——碰壁运动

    × 目录 [1]匀速碰壁 [2]自由落体 [3]投掷碰壁[4]拖拽碰壁 前面的话 碰撞运动可能是运动系列里面比较复杂的运动了.碰撞可以分为碰壁和互碰两种形式,而碰撞前后的运动形式也可以分为变速和匀速两 ...

  4. javascript运动系列第五篇——缓冲运动和弹性运动

    × 目录 [1]缓冲运动 [2]弹性运动 [3]距离分析[4]步长分析[5]弹性过界[6]弹性菜单[7]弹性拖拽 前面的话 缓冲运动指的是减速运动,减速到0的时候,元素正好停在目标点.而弹性运动同样是 ...

  5. Wee – 为现代 Web 开发打造的 CSS 脚手架

    Wee 包含许多开发人员在搭建响应的,互动的网站和应用程序时需要的组件.正如它的名字一样,Wee 是一个微小.移动优先的 CSS 复位框架.Wee 组织在一个简单的.可扩展的层次结构,拥有一致的样式和 ...

  6. js 运动函数篇(二) (加速度运动、弹性运动、重力场运动(多方向+碰撞检测+重力加速度+能量损失运动)拖拽运动)层层深入

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写加速度运动.弹性运动.重力场运 ...

  7. js 运动函数篇 (一) (匀速运动、缓冲运动、多物体运动、多物体不同值运动、多物体多值运动)层层深入

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写 匀速运动.缓冲运动.多物体运 ...

  8. 它来了,它来了,HarmonyOS应用开发在线体验来了

    接下来是我们的两分钟科普,一分钟玩转HarmonyOS应用开发在线体验,一分钟简单了解"一次开发.多设备部署"的原理.萌新的开发者也能第一时间掌握,往下看吧~ 一分钟玩转Harmo ...

  9. [转]教大家如何打造使用Tcpview(tcp查看器

    原文地址:教大家如何打造使用Tcpview(tcp查看器)作者:jybasenet3   一玩 VS 对战平台的同学有一次发现了一个可以踢人的方法,就是用 TcpView 把那个连 接关掉.后来VS ...

  10. 使用Vitamio打造自己的Android万能播放器(6)——在线播放(播放列表)

    前言 新版本的VPlayer由设计转入开发阶段,预计开发周期为一个月,这也意味着新版本的Vitamio将随之发布,开发者们可以和本系列文章一样,先开发其他功能.本章内容为"在线视频播放列表& ...

随机推荐

  1. jquery给一个li标签添加和去掉class属性

    $("li").addClass('xxx').siblings().removeClass("xxx");

  2. 【Java】常用类

    一.String类 java.lang.String类的使用 注意:String可以String s = "";,是因为String类型在后面自动补充了'\0' char初始化不能 ...

  3. .NET Core & ConsoleApp & appsettings.json

    准备 Visual Studio 2017 .NET Core 2.1 新建控制台应用(.NET Core) 默认的 Program.cs // Program.cs using System; na ...

  4. [COCI2014-2015#2] MOBITEL 题解

    题目大意 有一只蚂蚱,它把手机掉到了水坑里.然后它把手机捞出来,发现手机键盘都坏了. 那么手机没有坏之前就是介个样子的: 我们想打字的话就需要按下相应的数字键.比如说我们想打出 "a&quo ...

  5. 一些CF上的补题0504

    知识点模块 1.通过三点计算三角形的面积可以这样写 area=fabs(x1*y2-x2*y1+x2*y3-x3*y2+x3*y1-x1*y3)/2; 2.最小公倍数与最大公约数 x×y=gcd(x, ...

  6. 解决VSCODE进行C代码编辑时结构体成员不可见或不提示的问题

    在使用VSCODE进行C代码编辑时,结构体成员有时可见,光标放到成员上时,系统会提示结构体成员对应的注释信息,但是有时候却不行. 经过测试,发现有如下规律:以test.c test.h include ...

  7. rabbitmq分布式事务

    Rabbitmq解决分布式事务的原理:可靠消息最终一致性方案 需要保证以下三要素 1.确认生成者一定要将消息可靠投递到MQ[采用MQ的异步confirm消息确认机制] public interface ...

  8. python,提取数据,提取奇数位或者偶数位数据的方法

    如有数组num=["1","2","3","4","5"] 怎么按照奇.偶数位取数? 写法如下 nu ...

  9. 康谋分享 | aiSim5基于生成式AI扩大仿真测试范围(终)

    在前面的几章节中探讨了aiSim仿真合成数据的置信度,此外在场景重建和测试流程闭环的过程中,难免会面临3D场景制作重建耗时长.成本高.扩展性低以及交通状况复杂程度难以满意等问题,当前的主要挑战在于如何 ...

  10. Stream流式编程工具类,开发必备

    把自己写的流式编程工具分享出来,不涉及公司业务,非常便捷,不用在业务层看到一条龙式的Stream代码了: 大家用的最多的应该是转list,转set,以及setVFromE: 觉得好用点个赞就行 imp ...