Réaliser la fonction d'écoute du logiciel de lecture, s'adapter aux applications, aux petits programmes et h5
La fonction d'affichage des effets vous apporte : Chapitre, compte à rebours, chapitre précédent, chapitre suivant, lecture, pause, double vitesse :
uniapp officiel uni.createInnerAudioContext() adresse du document : adresse de référence du document du site officiel
Présentez d'abord la fonction étape par étape :
- Chapitre (cette interface d'appel peut parcourir les données et les afficher sous la forme d'une couche pop-up)
- Compte à rebours
- Chapitre précédent
- Chapitre suivant
- jouer
- pause
- double vitesse
J'intègre un composant audio sur cette page et le nom du composant est audio.
components: {
Audio},
data() {
return {
sourceList:[], //章节的数据
bookImg: '', //图书的封面图
bookName:'',//书名
chapterName: '', //章节名称
chapterUrl:'',//播放的章节地址
id: null, //书的id
itemId:'', //章节id
}
},
<template>
<view class="content">
<view class="" v-if="sourceList.length > 0">
<Audio @handleId='handleId' :sourceList='sourceList' :bookResourceId='bookResourceId' :bookName='bookName' :bookImg='bookImg' :id='id' :wxId='id' :chapterName='chapterName' :chapterUrl='chapterUrl'></Audio>
</view>
</view>
</template>
handleId(id){
this.id = id
},
Code de la page audio :
<template>
<view class="audio_content">
<view class="audio_box">
<image class="audio-img" :src="bookImg" mode="aspectFill"></image>
<view class="img-pop">
</view>
<view class="audio-info">
<!-- #ifdef APP-PLUS -->
<view class="header-box">
<u-icon name="arrow-left" style="margin-left: 32rpx;" color="#ffffff" size="24"
@click="goBack()"></u-icon>
<u-icon style="margin-right: 44rpx;" name="share-square" color="#ffffff" size="24"
@click="appShare"></u-icon>
</view>
<!-- #endif -->
<view class="course_name">
{
{
bookName}}
</view>
<view class="audio_title">
{
{
bgAudioMannager.title}}
<!-- {
{
bookTitle}} -->
</view>
<view class="book-box">
<image class="book-img" :src="bookImg" mode="aspectFill"></image>
</view>
<view class="audio_process">
<view class='slider'>
<!-- <slider :value="currentTime" step="1" min="0" :max="duration"
block-color="#fff" activeColor="#DC3232" inactiveColor="#8B8D7F" block-size="12"
@change="seek=true,clickSeek($event.detail.value)" @changing="seek=true,current=$event.detail.value" /> -->
<slider class="audio-slider" activeColor="#DC3232" block-size="12" :value="currentTime"
:max="duration" @changing="seek=true,current=$event.detail.value"
@change="seek=true,clickSeek($event.detail.value)"></slider>
</view>
<view class="time_cons">
<view class="duration">
{
{
time.getAudioTime(currentTime) }}
</view>
<view class="end">
{
{
time.getAudioTime(duration) }}
</view>
</view>
</view>
<view class="utils">
<view @tap="showModal">
<image class="change-list" :src="$staticUrl + 'static/index/audio-list.png'" mode="">
</image>
</view>
<view class="timeBox" @click="openTime">
<image class="change-time" :src="$staticUrl + 'static/index/audio-time.png'" mode="">
</image>
<view class="timeText">
{
{
timeMsg}}
</view>
</view>
<!-- 上一章 -->
<view class="">
<image v-if="!lastPlay" @click="lastMusic" class="change"
:src="$staticUrl + 'static/audio.png'" />
<image @click="lastMusic" class="change" v-if="lastPlay"
:src="$staticUrl + 'static/index/audio-pre.png'" />
</view>
<!-- 播放 -->
<view class="">
<image @click="playOrpause" v-if="!playStatus" class="change-start"
:src="$staticUrl + 'static/index/audio-start.png'" />
<image @tap="playOrpause" v-if="playStatus" class="change-start"
:src="$staticUrl + 'static/index/jgq_sxzt.png'" />
</view>
<!-- 下一章 -->
<view class="prev next">
<image @click="nextMusic" v-if="nextPlay" class="change"
:src="$staticUrl + 'static/index/audio-next.png'" />
<image v-if="!nextPlay" class="change" :src="$staticUrl + 'static/audio-g.png'" />
</view>
<view class="beisu" @click="showPlaybackRate = true">
<text class="num">{
{
rateText}}</text>
<!-- <text class="text">倍速播放</text> -->
</view>
</view>
</view>
</view>
<u-popup :show="hideModal" @close="close" @open="open" :round="10">
<!-- <view class="empty-box" id="empty-box"></view> -->
<scroll-view scroll-y style="height: 100%;">
<view class="content" :style="'transform:translateY(' + translateY + 'px);'" :animation="animate">
<view class="header">
<view class="title">
目录
</view>
<view class="right" @click="close">
<u-icon name="close" color="#000000" size="20"></u-icon>
</view>
</view>
<view>
<PeriodList :bookCoverImg='bookImg' :bookName='bookName' :supCode='supCode'
:sourceType='sourceType' :id='id' type='audio' :chapterList='sourceList'
@startAudio='startAudio' :bookResourceId='bookResourceId'></PeriodList>
</view>
</view>
</scroll-view>
</u-popup>
<!-- 倍速弹出层 -->
<u-popup :show="showPlaybackRate" @close="closePlaybackRate" @open="openPlaybackRate" :round="10">
<!-- <view class="empty-box" id="empty-box"></view> -->
<scroll-view scroll-y style="height: 100%;">
<view class="content" :style="'transform:translateY(' + translateY + 'px);'" :animation="animate">
<view class="header">
<view class="title">
倍速选择
</view>
<view class="right" @click="closePlaybackRate">
<u-icon name="close" color="#000000" size="20"></u-icon>
</view>
</view>
<view class="rate-listBox">
<view class="rate-list" @click="handleRate(0.5)">
0.5倍速
</view>
<view class="rate-list" @click="handleRate(1)">
1.0倍速
</view>
<view class="rate-list" @click="handleRate(1.5)">
1.5倍速
</view>
<view class="rate-list" @click="handleRate(2.0)">
2.0倍速
</view>
</view>
</view>
</scroll-view>
</u-popup>
<u-popup :show="showCloseTime" @close="closeTime" @open="openTime" :round="10">
<!-- <view class="empty-box" id="empty-box"></view> -->
<scroll-view scroll-y style="height: 100%;">
<view class="content" :style="'transform:translateY(' + translateY + 'px);'" :animation="animate">
<view class="header">
<view class="title">
设置倒计时关闭
</view>
<view class="right" @click="closeTime">
<u-icon name="close" color="#000000" size="20"></u-icon>
</view>
</view>
<view class="rate-listBox">
<!-- <view class="rate-list" @click="handleCloseTime(11)">
1分钟
</view>
<view class="rate-list" @click="handleCloseTime(12)">
5分钟
</view> -->
<view class="rate-list" @click="handleCloseTime(15)">
15分钟
</view>
<view class="rate-list" @click="handleCloseTime(30)">
30分钟
</view>
<view class="rate-list" @click="handleCloseTime(45)">
45分钟
</view>
<view class="rate-list" @click="handleCloseTime(1)">
1小时
</view>
<view class="rate-list" @click="handleCloseTime(2)">
2小时
</view>
</view>
</view>
</scroll-view>
</u-popup>
<!-- #ifdef APP-PLUS -->
<sharePop :shows="shows" :href="href" :title='title' @closes='closes'></sharePop>
<!-- #endif -->
</view>
</template>
Entrez d'abord la méthode d'initialisation de la page :
mounted() {
let that = this
that.initData()
},
initData() {
let that = this
// 页面加载设置当前播放章节的播放信息
this.bgAudioMannager = uni.createInnerAudioContext(); //只创建一次之后都是通过this.bgAudioMannager获取
this.bgAudioMannager.coverImgUrl = this.bookImg
this.bgAudioMannager.title = this.chapterName
this.bgAudioMannager.src = this.chapterUrl
// this.bgAudioMannager.playbackRate = 1.0 默认倍速为1.0
this.newId = this.id
this.duration = this.bgAudioMannager.duration
this.currentTime = this.bgAudioMannager.currentTime
this.currentId = this.id
this.startTime = this.getDate()
this.bgAudioMannager.onPlay(() => {
console.log('开始播放');
});
this.bgAudioMannager.onStop(() => {
console.log('停止播放');
});
this.bgAudioMannager.onPause(() => {
console.log('暂停播放');
});
this.bgAudioMannager.onEnded(() => {
//初始化 需要的参数
console.log('自然播放结束事件');
// this.nextMusic()
});
this.bgAudioMannager.onError((res) => {
console.log(res.errMsg);
console.log(res.errCode);
});
// 重要 缺失 音频进入可以播放状态
this.bgAudioMannager.onCanplay(() => {
this.currentTime = this.bgAudioMannager.currentTime
this.duration = this.bgAudioMannager.duration
console.log("可播放状态")
if (this.bgAudioMannager.duration) {
this.duration = this.bgAudioMannager.duration
console.log(this.bgAudioMannager.duration)
}
})
this.bgAudioMannager.play()
//音频进度更新事件
this.bgAudioMannager.onTimeUpdate(() => {
// console.log("开始监听")
/*
判断是否点击过进度条,若点击过,则不要对当前进度条时间current赋currentTime的值
因为音频进度更新事件运行频率过快,两个时间会引起冲突,
因此需要通过设置开关,判断seek真假,若seek为假则未点击进度条,若seek为真则跳过此次赋值并修改seek值重置为假
*/
if (!this.seek) {
this.currentTime = this.bgAudioMannager.currentTime
} else {
console.log("修改一次进度条")
// this.audio.seek(this.current_tmp)
// this.current = this.current_tmp
console.log(this.currentTime)
this.seek = false
}
if (this.bgAudioMannager.duration) {
this.duration = this.bgAudioMannager.duration
}
})
this.bgAudioMannager.onEnded(() => {
console.log('播放结束')
this.nextMusic()
});
},
Si vous devez mettre l'audio en pause au retour de la page :
onUnload() {
// clearInterval(timeSet); //停止调用
this.bgAudioMannager.pause()
this.newTime = 0;
this.playStatus = false //暂停播放的状态
this.bgAudioMannager.src = '' //当设置了新的 src 时,会自动开始播放
},
destroyed() {
this.bgAudioMannager.pause()
this.endTime = this.getDate()
},
Cliquez sur la barre de progression pour accéder à l'emplacement spécifié :
// 点击进度条
clickSeek(val) {
this.currentTime = val
this.bgAudioMannager.seek(val)
},
Fonction de lecture
playOrpause() {
//根据播放状态进行播放还是暂停
if (this.playStatus) {
this.bgAudioMannager.pause()
this.playStatus = false
} else {
this.bgAudioMannager.play()
this.playStatus = true
}
},
Pour le chapitre précédent et le chapitre suivant, notre structure de répertoires de chapitres est à deux niveaux. La logique est de trouver le chapitre correspondant dans le tableau de chapitres en fonction de l'identifiant de chapitre sur lequel vous avez cliqué, puis de prendre son nœud précédent ou son nœud suivant. : Remplacez l'identifiant obtenu par l'identifiant actuel
//上一首
lastMusic() {
let that = this
var currentIndex = null
var lastIndex = null
var currentIdx = null
this.bgAudioMannager.pause()
currentIndex = this.sourceList.findIndex((profile) => profile.id == that.id)
if (currentIndex == null || currentIndex == -1) {
this.sourceList.forEach((item, index) => {
//看当前id是否在子章节当中
currentIdx = item.twoLevelChapter.findIndex((item1) => item1.id == this.id)
lastIndex = item.twoLevelChapter.length - 1
//如果在父章节中找到,直接拿当前章节上一章节,通过下标-1的信息
if (currentIdx != -1) {
if (currentIdx != 0) {
this.bgAudioMannager.title = item.twoLevelChapter[currentIdx - 1].chapterName
this.bgAudioMannager.coverImgUrl = item.twoLevelChapter[currentIdx - 1].chapterUrl
this.bgAudioMannager.src = item.twoLevelChapter[currentIdx - 1].chapterUrl
that.newId = item.twoLevelChapter[currentIdx - 1].id
that.$emit('handleId', this.newId)
this.nextPlay = true
this.playStatus = true
this.bgAudioMannager.play()
} else {
//如果刚好拿到的是第一章节就直接给提示
if (index == 0) {
this.bgAudioMannager.title = item.twoLevelChapter[0].chapterName
this.bgAudioMannager.coverImgUrl = item.twoLevelChapter[0].chapterUrl
this.bgAudioMannager.src = item.twoLevelChapter[0].chapterUrl
that.newId = item.twoLevelChapter[0].id
uni.showToast({
title: '没有上一章节了',
icon: 'none'
})
return
} else {
this.bgAudioMannager.title = that.sourceList[index - 1].chapterName
this.bgAudioMannager.coverImgUrl = that.sourceList[index - 1].coverImgUrl
this.bgAudioMannager.src = that.sourceList[index - 1].chapterUrl
that.newId = that.sourceList[index - 1].id
that.$emit('handleId', this.newId)
}
}
}
})
} else {
lastIndex = this.sourceList.length - 1
if (currentIndex != 0) {
this.bgAudioMannager.title = that.sourceList[currentIndex - 1].chapterName
this.bookTitle = this.bgAudioMannager.title
console.log('title', this.bgAudioMannager.title)
this.bgAudioMannager.coverImgUrl = this.sourceList[currentIndex - 1].coverImgUrl
this.bgAudioMannager.src = this.sourceList[currentIndex - 1].chapterUrl
this.newId = this.sourceList[currentIndex - 1].id
that.$emit('handleId', this.newId)
this.nextPlay = true
this.playStatus = true
this.bgAudioMannager.play()
} else {
this.bgAudioMannager.title = that.sourceList[0].chapterName
this.bgAudioMannager.src = this.sourceList[0].chapterUrl
this.newId = this.sourceList[0].id
this.bgAudioMannager.play()
uni.showToast({
title: '已经是第一章了',
icon: 'none'
})
return
}
}
this.id = this.newId
},
// 下一首
nextMusic() {
let that = this
var currentIndex = null
var lastIndex = null
var currentIdx = null
this.bgAudioMannager.pause()
currentIndex = this.sourceList.findIndex((profile) => profile.id == this.id)
if (currentIndex == null || currentIndex == -1) {
this.sourceList.forEach(item => {
currentIdx = item.twoLevelChapter.findIndex((item1) => item1.id == this.id)
lastIndex = item.twoLevelChapter.length - 1
if (currentIdx != -1) {
if (currentIdx != lastIndex) {
this.bgAudioMannager.title = item.twoLevelChapter[currentIdx + 1].chapterName
this.bgAudioMannager.coverImgUrl = item.twoLevelChapter[currentIdx + 1].chapterUrl
this.bgAudioMannager.src = item.twoLevelChapter[currentIdx + 1].chapterUrl
this.id = item.twoLevelChapter[currentIdx + 1].id
this.nextPlay = true
this.playStatus = true
this.bgAudioMannager.play()
} else {
this.bgAudioMannager.title = that.sourceList[currentIndex + 1].chapterName
this.bgAudioMannager.coverImgUrl = that.sourceList[currentIndex + 1].chapterUrl
this.bgAudioMannager.src = that.sourceList[currentIndex + 1].chapterUrl
that.id = that.sourceList[currentIndex + 1].id
this.bgAudioMannager.play()
}
}
})
} else {
lastIndex = this.sourceList.length - 1
if (currentIndex != lastIndex) {
this.bgAudioMannager.title = this.sourceList[currentIndex + 1].chapterName
this.bgAudioMannager.coverImgUrl = this.sourceList[currentIndex + 1].chapterUrl
this.bgAudioMannager.src = this.sourceList[currentIndex + 1].chapterUrl
this.id = this.sourceList[currentIndex + 1].id
this.nextPlay = true
this.playStatus = true
this.bgAudioMannager.play()
} else {
this.bgAudioMannager.title = this.sourceList[lastIndex].chapterName
this.bgAudioMannager.coverImgUrl = this.sourceList[lastIndex].chapterUrl
this.bgAudioMannager.src = this.sourceList[lastIndex].chapterUrl
this.id = this.sourceList[lastIndex].id
this.bgAudioMannager.play()
uni.showToast({
title: '已经是最后一章了',
icon: 'none'
})
return
}
}
//如果播放自动播放完就自动切换下一章
this.bgAudioMannager.onEnded(() => {
//初始化 需要的参数
console.log('自然播放结束eee事件');
this.nextMusic()
});
},