效果展示
实现思路
- 传统操作音乐播放:传统写项目(淘宝京东)就是一个个html文件,里面写Javascript代码(切记不允许全部看代码,看大步骤)
1 获取音乐对象 player
2 调用api 播放play、暂定pause等等
ini
<audio
controls
src="http://tmp00002.zhaodashen.cn/mp3/chenyixun_000z2oXY18Hsli.m4a"
></audio>
<button id="playerBtn">播放</button>
<button id="pausereBtn">暂停</button>
<script>
// 1 获取实例
const player = document.querySelector("audio");
// console.log("player::: ", player);
// 2 调用api播放
playerBtn.onclick = () => {
player.play();
};
pausereBtn.onclick = () => {
player.pause();
};
</script>
- 鸿蒙操作音乐播放语法
javascript
import {media} from '@kit.MediaKit'
// ✅ 1. 创建音乐播放器对象
const player:media.AVPlayer = await media.createAVPlayer()
// ✅ 2. 侦听播放状态(监控设置地址)
player.on('stateChange', (state) => {
switch(state) {
// 初始化状态
case 'initialized':
player.prepare() // 准备就绪态
break;
// 准备就绪态
case 'prepared':
player.play() // 播放
break;
}
})
player.on('durationUpdate', (duration) => {}) // 歌曲时长
player.on('timeUpdate', (data) => {}) // 播放时长
player.on('volumeChange', () => {}) // 音量
// ✅ 3. 调用API控制状态
// - 播放地址
player.url = 播放源地址
// - 切换播放地址
await player.reset()
player.url = 播放源地址
// - 暂停
player.pause()
// - 音量
player.setVolume(0~1范围)
// - 循环播放
player.loop = 布尔
// - 播放速率
player.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_0_75_X)
player.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_00_X)
player.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_25_X)
player.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_75_X)
player.setSpeed(media.PlaybackSpeed.SPEED_FORWARD_2_00_X)
// - 本地播放
//这里的音频资源是放在rawfile文件夹中的.mp3文件,读者自己设置其他文件资源。
//给播放器设置播放资源,上图有参考资料,使用的是fsSrc资源,不是网络资源->。
const fd = getContext().resourceManager.getRawFdSync(name)
this.avplayer.fdSrc = { fd: fd.fd, offset: fd.offset, length: fd.length }
完整代码
ini
import {media} from '@kit.MediaKit'
export class DateUtil {
static m2s(ms:number) {
// 分钟 = parseInt(总毫秒/1000/60) 得到分钟然后不够补0 这个parseInt是为了去掉小数
const m = parseInt(String(ms/1000/60)).toString().padStart(2,'0');
// 秒数 = parseInt(总毫秒/100得到秒 - 分占用的秒) 最终秒数 不够补0
// const s = parseInt(String(ms/1000 - parseInt(m)*60)).toString().padStart(2,'0')
const s = parseInt(String(ms/1000%60)).toString().padStart(2,'0')
return `${m}:${s}`
}
}
@Entry
@Component
struct Index {
// "[al:认了吧]"
// "[00:00.00]爱情转移 - 陈奕迅 (Eason Chan)"
// "[00:05.73]词:林夕"
@State currentLrc:string = ''
private lrc: string[] = "[ti:爱情转移 (《爱情呼叫转移》电影主题曲|《富士山下》国语版)]\n[ar:陈奕迅]\n[al:认了吧]\n[by:]\n[offset:0]\n[00:00.00]爱情转移 - 陈奕迅 (Eason Chan)\n[00:05.73]词:林夕\n[00:11.47]曲:泽日生\n[00:17.21]编曲:陈珀/C.Y.Kong\n[00:22.95]徘徊过多少橱窗\n[00:25.29]住过多少旅馆\n[00:27.54]才会觉得分离也并不冤枉\n[00:31.89]感情是用来浏览\n[00:34.15]还是用来珍藏\n[00:36.55]好让日子天天都过得难忘\n[00:40.98]熬过了多久患难\n[00:43.37]湿了多少眼眶\n[00:45.63]才能知道伤感是爱的遗产\n[00:50.22]流浪几张双人床\n[00:52.63]换过几次信仰\n[00:54.77]才让戒指义无反顾的交换\n[00:59.28]把一个人的温暖\n[01:01.70]转移到另一个的胸膛\n[01:04.74]让上次犯的错反省出梦想\n[01:08.48]\n[01:08.98]每个人都是这样\n[01:11.27]享受过提心吊胆\n[01:13.74]才拒绝做爱情待罪的羔羊\n[01:18.21]回忆是抓不到的月光握紧就变黑暗\n[01:22.84]等虚假的背影消失于晴朗\n[01:26.67]\n[01:27.34]阳光在身上流转\n[01:29.53]等所有业障被原谅\n[01:32.62]\n[01:34.94]爱情不停站\n[01:36.78]想开往地老天荒\n[01:39.34]需要多勇敢\n[01:41.35]\n[01:43.58]烛光照亮了晚餐\n[01:45.95]照不出个答案\n[01:48.20]恋爱不是温馨的请客吃饭\n[01:52.18]\n[01:52.69]床单上铺满花瓣\n[01:55.11]拥抱让它成长\n[01:57.33]太拥挤就开到了别的土壤\n[02:01.79]感情需要人接班\n[02:04.22]接近换来期望\n[02:06.51]期望带来失望的恶性循环\n[02:10.96]短暂的总是浪漫\n[02:13.31]漫长总会不满\n[02:15.57]烧完美好青春换一个老伴\n[02:19.59]\n[02:20.12]把一个人的温暖\n[02:22.45]转移到另一个的胸膛\n[02:25.28]让上次犯的错反省出梦想\n[02:29.14]\n[02:29.86]每个人都是这样\n[02:32.03]享受过提心吊胆\n[02:34.42]才拒绝做爱情待罪的羔羊\n[02:39.01]回忆是抓不到的月光握紧就变黑暗\n[02:43.54]等虚假的背影消失于晴朗\n[02:47.43]\n[02:48.08]阳光在身上流转\n[02:50.38]等所有业障被原谅\n[02:53.37]\n[02:54.86]爱情不停站\n[02:56.83]想开往地老天荒\n[02:59.79]需要多勇敢\n[03:01.88]\n[03:04.22]把一个人的温暖\n[03:06.75]转移到另一个的胸膛\n[03:09.60]让上次犯的错反省出梦想\n[03:13.70]\n[03:14.21]每个人都是这样\n[03:16.61]享受过提心吊胆\n[03:19.08]才拒绝做爱情待罪的羔羊\n[03:23.82]回忆是抓不到的月光握紧就变黑暗\n[03:28.46]等虚假的背影消失于晴朗\n[03:32.54]\n[03:33.11]阳光在身上流转\n[03:35.47]等所有业障被原谅\n[03:38.67]\n[03:42.48]爱情不停站\n[03:44.28]想开往地老天荒\n[03:47.24]\n[03:47.82]需要多勇敢\n[03:50.26]\n[03:53.07]你不要失望\n[03:54.75]荡气回肠是为了\n[03:57.64]最美的平凡".split('\n')
@State duration:number = 0
@State currentTime:number = 0
// private player: media.AVPlayer = {} as media.AVPlayer
// private player: media.AVPlayer = {} as ESObject
private player: media.AVPlayer = Object()
async aboutToAppear() {
// ✅ 1. 创建音乐播放器对象
// const player:media.AVPlayer = await media.createAVPlayer() 切记player放外面 后期要操作
this.player = await media.createAVPlayer()
// ✅ 2. 侦听播放状态
this.player.on('stateChange', (state) => {
switch(state) {
// 初始化状态
case 'initialized':
console.log('11111 initialized')
this.player.prepare() // 准备就绪态
break;
// 准备就绪态
case 'prepared':
console.log('2222 prepared')
this.player.play() // 播放
break;
}
})
this.player.on('durationUpdate', (duration) => { // 歌曲时长
console.log('歌曲时长:', duration)
this.duration = duration
})
this.player.on('timeUpdate', (time) => { // 播放时长
console.log('播放时长:', time)
this.currentTime = time
for (let i=0; i<this.lrc.length; i++) {
const item = this.lrc[i]
const m2s = item.slice(1,6) // '01:11'
if (DateUtil.m2s(time) === m2s) {
this.currentLrc = item.slice(10)
}
}
})
// this.player.on('volumeChange', () => {}) // 音量
}
build() {
Column() {
Text('hello music').fontSize(30)
Button('打开界面(设置播放链接)').onClick(() => {
this.player.url = 'http://tmp00002.zhaodashen.cn/mp3/chenyixun_003u2qmP0Mp2pW.m4a'
}).margin({bottom:20})
Button('播放').onClick(() => this.player.play()).margin({bottom:20})
Button('暂停').onClick(() => this.player.pause()).margin({bottom:20})
Button('换一首').onClick(async () => {
await this.player.reset()
this.player.url = 'http://tmp00002.zhaodashen.cn/mp3/wangjingwenbupang_0017ZGNs0ISfYi.m4a'
}).margin({bottom:20})
Text(`播放进度:${this.currentTime} 、 ${this.duration}`).fontSize(20)
Text(DateUtil.m2s(this.currentTime)).fontSize(20)
Slider({
value: this.currentTime,
min: 0,
max: this.duration,
style: SliderStyle.OutSet
})
.showTips(true)
.onChange((value: number, mode: SliderChangeMode) => {
console.info('value:' + value + 'mode:' + mode.toString())
if (mode === 2) {
this.player.seek(value)
}
})
Text(DateUtil.m2s(this.duration)).fontSize(20).margin({bottom:50})
Text('音量🔊').fontSize(20)
Slider({
value: 100,
min: 0,
max: 100,
style: SliderStyle.OutSet
})
.showTips(true)
.onChange((value: number, mode: SliderChangeMode) => {
console.info('value:' + value + 'mode:' + mode.toString())
// this.player.setVolume(0~1范围)
this.player.setVolume(value/100)
})
Text(this.currentLrc).fontSize(30)
}.padding(50)
}
}
