前提:
参考:(真机这样写还是有问题)
《1》构造npm:
- https://blog.youkuaiyun.com/zxh7770/article/details/105108779
《2》小程序:
- https://developers.weixin.qq.com/community/develop/doc/000ac4d78f41503fe059037b656400
1、场景:初始化跳转到上次播放的位置,可前进后退各15s的时间
2、出现问题:
- seek后出现onTimeUpdate监听失效,无法更新当前的进度条(进度条设置在监听中了)
3、问题原因:
- seek 跳转需要先puse暂停后再play才可以监控到
4、解决问题
- 点击seek时再onSeek监听中去暂停puse,在onCanplay中去开启播放play,就可以解决了
- 关键代码如下:
this.innerAudioContext.onSeeking(()=>{ this.innerAudioContext.pause() }) this.innerAudioContext.onCanplay(() => { this.innerAudioContext.play() })
- 功能实现(详情如下)
// pages/knowladgedetailinfo/knowladgedetailinfo.js
const moment = require('moment') //这个插件需要下载
Page({
/**
* 页面的初始数据
*/
data: {
isPlay:false,//是否播放 true:播放
currentTime:0,
currentWidth:0,
url:'https://XXXXXX.mp3',
duration:0,//总时间长度
},
//获取文章详情-就是后端返回音频的url和当前时间的一些业务信息
getArticleDetail(){
//例如 this.setData({//currentTime、url})
},
//点击播放
handleMusicPlay(){
let isPlay = !this.data.isPlay;
// 修改是否播放的状态
this.setData({
isPlay,
})
this.musicControl(isPlay, this.data.audio);
},
// 控制音乐播放/暂停的功能函数
musicControl(isPlay, musicLink){
const {currentTime} = this.data
if(isPlay && musicLink){ // 音乐播放
this.innerAudioContext.autoplay = isPlay //是否自动播放
this.innerAudioContext.src = musicLink
this.innerAudioContext.seek(currentTime)
}else{
this.innerAudioContext.pause();
}
},
// 修改播放状态的功能函数
changePlayState(isPlay){
// 修改音乐是否的状态
this.setData({
isPlay
})
},
//播放前进后退
handleTime(item){
if(item.currentTarget.dataset.type==='left'){
this.innerAudioContext.currentTime>15?this.innerAudioContext.seek((this.innerAudioContext.currentTime-15)):this.innerAudioContext.seek(0)
}else{
this.innerAudioContext.currentTime>totalTime?this.innerAudioContext.seek(totalTime):this.innerAudioContext.seek((this.innerAudioContext.currentTime+15))
}
},
//提交-保存当前记录播放截止记录(后端接口提供创建记录保存最后播发的时间)
handleSubmitTime(){
console.log('时间提交',this.data.cognitionId)
},
//创建audio
handleCreateAudio(){
this.innerAudioContext = wx.createInnerAudioContext()
this.innerAudioContext.onPlay(() => {
this.changePlayState(true);
})
this.innerAudioContext.onPause(()=>{
this.changePlayState(false);
})
this.innerAudioContext.onCanplay(() => {
this.innerAudioContext.play()
})
this.innerAudioContext.onTimeUpdate(()=>{
let currentTime = moment(this.innerAudioContext.currentTime * 1000).format('mm:ss')
let currentWidth = this.innerAudioContext.currentTime/this.innerAudioContext.duration * 450;
this.setData({
currentTime,
currentWidth,
})
})
this.innerAudioContext.onSeeking(()=>{
this.innerAudioContext.pause()
})
this.innerAudioContext.onEnded(()=>{
this.setData({
currentWidth: 0,
currentTime: '00:00',
})
this.changePlayState(false);
})
this.innerAudioContext.onError((res) => {
this.changePlayState(false);
})
},
/**
* 生命周期函数--监听页面加载
*/
async onLoad(options) {
this.getArticleDetail() //初始化从后端接口中获取播放参数
this.handleCreateAudio() //初始化创建audio实例然后进行设置和监听
},
/**
* 生命周期函数--监听页面隐藏
*/
async onHide() { //隐藏前向后端提交当前记录的播放+销毁innerAudioContext
if(this.data.isClick){
await this.handleSubmitTime()
this.innerAudioContext.pause()
this.innerAudioContext.destroy()
}
},
/**
* 生命周期函数--监听页面卸载
*/
async onUnload() { //隐藏前向后端提交当前记录的播放+销毁innerAudioContext
if(this.data.isClick){
await this.handleSubmitTime()
this.innerAudioContext.pause()
this.innerAudioContext.destroy()
}
},
})
- 模块样式实现
<view class="mp3_card">
<view class="mp3_time">
时长:{{timeH}}分{{timeS}}秒
</view>
<view class="mp3_function">
<view class="item">
<image style="width:50rpx;height:50rpx" src="../../images/mp3left_cirletime.png" alt='左播放' data-type="left" bindtap="handleTime"></image>
</view>
<view class="item">
<image hidden="{{isPlay}}" style="width:104rpx;height:104rpx" src="../../images/mp3stop.png" bindtap="handleMusicPlay"></image>
<image hidden="{{!isPlay}}" style="width:104rpx;height:104rpx" src="../../images/knowledge/start.png" bindtap="handleMusicPlay"></image>
</view>
<view class="item">
<image style="width:50rpx;height:50rpx" src="../../images/mp3right_cirletime.png" alt='右播放' data-type="right" bindtap="handleTime"></image>
</view>
</view>
<view class='mp3_schedule'>
<view class="sechedule_num" style="width: {{currentWidth?currentWidth + 'rpx':0}}">
<view class="schedule_icon">
{{currentTime}}/{{duration}}
</view>
</view>
</view>
</view>
模块的样式
.mp3_card{
box-sizing: border-box;
padding: 20rpx 58rpx 38rpx 58rpx;
margin-top: 32rpx;
height: 270rpx;
border-radius: 16rpx;
background: #FFFFFF;
box-shadow: 0 0 20rpx 0 rgba(0, 0, 0, 0.3);
}
.mp3_time{
font-family: SourceHanSansCN-Regular;
font-size: 24rpx;
font-weight: normal;
line-height: 44rpx;
letter-spacing: 0em;
color: #3D3D3D;
}
.mp3_function{
margin-top: 24rpx;
display: flex;
flex-direction: row;
justify-content: center;
justify-items: center;
}
.mp3_function >.item{
text-align: center;
margin: auto;
flex: 1;
}
.mp3_schedule{
margin-top: 30rpx;
width: 100%;
height: 4rpx;
background-color:#D8D8D8 ;
/* border-bottom: 4rpx solid #D8D8D8; */
position: relative;
}
.sechedule_num{
position: relative;
height: 4rpx;
top: 0rpx;
left:0rpx;
line-height: 4rpx;
background-color:#FAB71C;
}
.schedule_icon{
position: absolute;
text-align: center;
top: -20rpx;
right: -140rpx;
width: 140rpx;
height: 40rpx;
border-radius: 40rpx;
/* Text/Secondary */
background: #767676;
font-family: SourceHanSansCN-Regular;
font-size: 10px;
line-height: 40rpx;
font-weight: normal;
letter-spacing: 0em;
color: #FFFFFF;
}