效果如↓↓↓ 假装有声音。
很郁闷,没有做到完全解耦,试了试音频播放组件与API wx.createInnerAudioContext()在自定义控件中没有作用!
也就是说,不能只传一个语音的url给自定义的控件了!播放的控制还得放在页面中,控制播放、暂停、等标识数据都得传,说是自定义控件,其实也就是一个UI罢了,与安卓IOS的继承再封装没法比,与小程序中引用片段 相比 还没有人家简单。
个人认为:小程序的自定义组件是没有灵魂的,与引用片段无本质区别,当然,这是我乱说的,欢迎大神指导...
然后上代码吧:希望能抛砖引玉
1.在合适的目录右键新建component 自定义控件voice-view
wxml:
{{length}}s
wxss:
/* components/voice-view.wxss */
.voices {
padding: 10rpx 0;
display: flex;
flex-direction: row;
align-items: center;
}
.voices .voice {
width: 320rpx;
height: 40rpx;
background: rgba(35, 69, 156, 1);
border-radius: 20rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.voices .voice-hover{
background: rgb(28, 54, 121);
}
.voices .voice image {
width: 26rpx;
height:26rpx;
}
js:
// components/voice-view.js
Component({
/**
* 组件的属性列表
*/
properties: {
index: {
type: Number,
value: 0
},
length: {
type: Number,
value: 10,
},
url: {
type: String,
value: ''
},
playing: {
type: Boolean,
value: false,
observer: "playAnima" // observer 表示属性值被更改时的响应函数
}
},
/**
* 组件的初始数据
*/
data: {
voiceImg: 3,
},
/**
* 组件的方法列表
*/
methods: {
//伪动画播放方法
playAnima: function() {
var that = this
if (!that.data.playing) {
this.setData({
voiceImg: 3
})
} else {
switch (that.data.voiceImg) {
case 1:
that.setData({
voiceImg: 2
})
break
case 2:
that.setData({
voiceImg: 3
})
break
case 3:
that.setData({
voiceImg: 1
})
break
}
setTimeout(function() {
that.playAnima()
}, 500)
}
},
//播放、暂停音频
playVoice: function(e) {
this.triggerEvent('voiceClickss', {
index: this.data.index,
url:this.data.url,
playing:this.data.playing
});
},
},
})
2.page引用:要引用的先加声明:page页面的json中:
{
"usingComponents": {
"voice-view":"../../components/voice-view"
},
"navigationBarTitleText": "test"
}
布局wxml:
注意:url、length、等都是自定义控件中properties的属性。
bind:voiceClickss='voiceClick' 的意思是:绑定自定义控件中“voiceClickss”方法至page页面中“voiceClick”方法
当点击自定义控件时,执行控件中:
playVoice: function(e) {
this.triggerEvent('voiceClickss', {
index: this.data.index,
url:this.data.url,
playing:this.data.playing
});
},
将执行page页面中方法,并传值index...
js:
// pages/test/test.js
var playingSrc = ''
var playingIndex = 0
const innerAudioContext = wx.createInnerAudioContext()
Page({
data: {
list: [{
url: 'https://fanyi.baidu.com/gettts?lan=en&text=%20pop%2Fdance%2Fclassical%2Fchurch%20music%20&spd=3&source=web',
length: 3,
playing: false
},
{
url: 'https://fanyi.baidu.com/gettts?lan=en&text=She%20could%20hear%20music%20playing%20somewhere.&spd=3&source=web',
length: 4,
playing: false
},
{
url: 'https://fanyi.baidu.com/gettts?lan=en&text=the%20popularity%20of%20Mozart%27s%20music&spd=3&source=web',
length: 8,
playing: false
},
],
},
//播放、暂停音频
voiceClick: function(e) {
console.log('page,-----voiceClick',)
var index = e.detail.index
playingIndex = index
var playing = e.detail.playing
var src = this.data.list[index].url
console.log('播放url', src)
if (playingSrc != src) {
innerAudioContext.stop()
innerAudioContext.src = src
playingSrc = src
innerAudioContext.play()
} else if (!playing) {
console.log('暂停中---->播放')
innerAudioContext.play()
} else {
console.log('播放中---->暂停')
innerAudioContext.pause()
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
var that = this
innerAudioContext.autoplay = false
innerAudioContext.obeyMuteSwitch = false
innerAudioContext.onPlay(function() {
that.setStatus(true)
})
innerAudioContext.onPause(function() {
that.setStatus()
})
innerAudioContext.onStop(function() {
that.setStatus()
})
innerAudioContext.onEnded(function() {
that.setStatus()
})
innerAudioContext.onError(function(res) {
that.setStatus()
var t = '未知错误'
switch (res.errCode) {
case 10001:
t = '系统错误'
break;
case 10002:
t = '网络错误'
break;
case 10003:
t = '文件错误'
break;
case 10004:
t = '格式错误'
break;
}
wx.showToast({
title: t,
icon: 'none'
})
})
},
setStatus: function(sta = false) {
for (var i = 0; i < this.data.list.length; i++) {
this.data.list[i].playing = false
}
if (sta)
this.data.list[playingIndex].playing = true
this.setData({
list: this.data.list
})
}
})
开发中发现微信自带的判断音频播放是否暂停状态的方法不好用!无奈只好另写了个变量播放状态playing
wx文档: boolean paused 当前是是否暂停或停止状态(只读)
哦,顺便把图片资源文件给大家: