最近两周在写一个新的小程序项目,托福词汇真经。这个小程序的难点是音频播放流程比较复杂
之前我在雅思听力小程序里实现过雅思词汇真经的功能
前期讨论的结果是基于原有的功能开发
开发过程中碰到了一些问题,这里记录一下,同时梳理一下这里音频播放的逻辑,后面如果再增加新功能,可以快速处理
闲话少叙
这里讨论的页面是: wordsZhenjing.js
四种模式介绍
这个页面的音频播放最开始只有两个模式:1.循环听 2.听写
后来增加了在线拼写模式,这次又增加了测试模式。但是这两种模式的详情页都是新的页面,逻辑不在这里,这里不讨论
循环听VS听写 最开始使用 isListen 这个布尔值变量区分,但是后来增加了拼写和测试模式,所以现在使用modeIndex变量区分(0:测试; 1:循环听; 2:听写; 3:拼写) 。
所以isListen是否可以去掉呢? xml里面使用了这个变量,先留着吧
旧的模式介绍
听写模式: 只播放单词。播放完毕去对答案
循环听模式:播放单词,例句, 同替,过去式,过去分词。这个单词的相关信息播放完,继续播放下一个单词的例句,同替,过去式...
一组全部播放完毕,根据不同设置,可以重头播放这一组,也可以播放下一组
旧的关键逻辑
Q:循环听模式是怎么顺序播放 单词,例句,同替,单词,例句,同替...... 如此循环的呢?
A: 每个单词的例句, 同替,过去式格式化成数组 formAudios, 追加字段audioInfos, 增加一个innerIdx 字段,用于在单词的 audioInfos 数组里面顺序播放音频
/**
* 格式化音频
*/
formAudios(list) {
list.forEach((item) => {
let audioInfos = typeof (item.near) != 'undefined' ? Array.from(item.near) : []
if (item.past) {
audioInfos.push(...item.past)
}
if (item.participle) {
audioInfos.push(...item.participle)
}
if (item.template && item.template.url.length > 0) {
let tempItem = {
tag: 'template',
url: item.template.url,
text: item.template.en
}
audioInfos.unshift(tempItem)
}
let wordItem = {
tag: 'word',
url: item.url,
text: item.text
}
audioInfos.unshift(wordItem)
item.audioInfos = audioInfos
// console.log('检查----',audioInfos)
})
},
接口返回的数据格式:
输出结果:
播放逻辑:
// 1洗脑听单词,下一个音频判断逻辑
function listenToNext() {
if (this.hasPlayGroupUrl) {
this.hasPlayGroupUrl = false
this.inLogic_xiNaoNext()
this.listen2NextWord()
} else {
let currWordItem = this.data.currWordItem
if(!currWordItem.text){ //判断是否是拓展
this.expandStart()
return
}
// 根据innerIdx 判断是否播放到这一组的边缘
if (this.data.innerIdx < 0) {
console.log('item??--',this.data.currWordItem)
if(this.data.currWordItem){ //听写同替到头,切换洗脑听,重复播放间隔音bugFix
this.playMainUrl()
this.setData({
innerIdx: 0
})
}
}
else if (this.data.innerIdx < currWordItem.audioInfos.length - 1) {
if (this.isPlayInnerGapAudio) {
this.isPlayInnerGapAudio = false
this.playIntervalUrl()
} else {
this.isPlayInnerGapAudio = true
this.data.innerIdx++
// 如果下一个是同替才播, 其他都不播, 下标++ todo:抽取优化
if(this.data.dictateSynonym && this.data.modeIndex == 2){
let nextInfor = currWordItem.audioInfos[this.data.innerIdx]
if(nextInfor.tag == '同替'){
this.initAudio()
let codeUrl = encodeURI(currWordItem.audioInfos[this.data.innerIdx].url)
this.backgroundAudioManager.src = codeUrl
this.backgroundAudioManager.playbackRate = parseFloat(this.data.speed)
this.backgroundAudioManager.play()
this.setData({
innerIdx: this.data.innerIdx
})
}else {
this.setData({
innerIdx: this.data.innerIdx
})
this.isPlayInnerGapAudio = false
this.playIntervalUrl()
}
}else {
this.initAudio()
let codeUrl = encodeURI(currWordItem.audioInfos[this.data.innerIdx].url)
this.backgroundAudioManager.src = codeUrl
this.backgroundAudioManager.playbackRate = parseFloat(this.data.speed)
this.backgroundAudioManager.play()
this.setData({
innerIdx: this.data.innerIdx
})
}
}
} else {
if (this.isPlayInterval) {
this.repetitionCount--
if (this.repetitionCount <= 0) { //bugFix:播放两遍拓展
// 播放间隔音
// 当前没有同替,不播放间隔音
if(currWordItem.near){
this.listenPlayInterval()
this.hasPlayGroupUrl = true
} else {
this.hasPlayGroupUrl = false
this.inLogic_xiNaoNext()
this.listen2NextWord()
}
// 如果到头了,让下标++
if(this.data.wordIndex == this.data.wordArr.length - 1){
let idx = this.data.wordIndex
this.setData({
wordIndex: idx++
})
}
} else if (this.repetitionCount > 0) {
this.listen2NextWord()
this.setData({
innerIdx: -1
})
}else {
this.inLogic_xiNaoNext()
this.listen2NextWord()
this.setData({
innerIdx: -1
})
}
}
}
}
}
这次新增的需求:
【需求1】循环听模式,单词听完了,如果有拓展,播放拓展
【需求2】听写模式,如果有同替,可以听写同替
【需求1】
Q: 如何实现?
A:一组音频播放完,检查当前currWordItem是否是拓展,是拓展就播放拓展。是否是拓展的判断如下:
if(!currWordItem.text){ //判断是否是拓展
this.expandStart()
return
}
用字段为空这么判断可能不太优雅,先这样吧
【需求2】
Q: 如何实现?
A: 增加字段 dictateSynonym, 在toNext函数里面判断 如果是dictateSynonym的情况,也调用dictateSynonym:
function toNext() {
if (util.noRepeatTap(this, 100)) {
return
}
if (this.data.isPlay) {
if (this.data.isListen) {
console.log('check idx->',this.data.wordIndex)
this.listenToNext()
return
}
// 听写同替模式
if(this.data.dictateSynonym){
this.listenToNext()
return
}
if (this.isPlayInterval) {
this.repetitionCount--
if (this.repetitionCount == 0) {
this.data.wordIndex++
this.repetitionCount = parseInt(this.data.repetition)
}
}
// 播放完成
if (this.data.wordIndex >= this.data.wordArr.length) {
this.setData({
isEnd: true,
isPlay: false,
})
this.playChange(this.data.isPlay)
this.audioFinish()
} else {
this.data.currWordItem = this.data.wordArr[this.data.wordIndex]
if (this.isPlayInterval) {
var intervalCount = parseInt(this.data.interval)
this.isPlayInterval = false
var intervalAudioUrl = ""
console.log('listen count->',intervalCount)
switch (intervalCount) {
case 1:
intervalAudioUrl = intervalAudio1
break;
case 2:
intervalAudioUrl = intervalAudio2
break;
case 3:
intervalAudioUrl = intervalAudio3
break;
case 4:
intervalAudioUrl = intervalAudio4
break;
case 5:
intervalAudioUrl = intervalAudio5
break;
case 7:
intervalAudioUrl = intervalAudio7
break;
case 10:
intervalAudioUrl = intervalAudio10
break;
default:
intervalAudioUrl = intervalAudio1
break;
}
this.initAudio()
this.backgroundAudioManager.playbackRate = 1.0
this.backgroundAudioManager.src = intervalAudioUrl
this.backgroundAudioManager.play()
} else {
console.log(this.data.currWordItem.url)
this.playMainUrl()
this.setData({
currWordItem: this.data.currWordItem,
wordIndex: this.data.wordIndex,
percent: (this.data.wordIndex + 1) / this.data.wordArr.length * 100,
})
}
}
}
}
遇到的问题:
增加播放拓展的逻辑-前进后退-自动播放完切换下一个音频
svSupListen.js listenToNext 一百行逻辑
同步弹窗选中的跟保存的记录