[Feature] 完成音频播放部分

This commit is contained in:
zhengyi 2023-03-03 16:03:11 +08:00
parent 0871ceae4e
commit 4aa6f82fa8
11 changed files with 250 additions and 9 deletions

View File

@ -0,0 +1,27 @@
// components/poem-audio/audio-controls/audio-controls.js
Component({
/**
* 组件的属性列表
*/
properties: {
currTime: Number,
fullTime: Number,
isPlaying: Boolean
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
toggle() {
this.triggerEvent('toggle')
}
}
})

View File

@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"t-icon": "tdesign-miniprogram/icon/icon",
"t-progress": "tdesign-miniprogram/progress/progress"
}
}

View File

@ -0,0 +1,38 @@
<view class="controles">
<view class="slider">
<view class="time">
<text class="curr">{{we.formatTime(currTime)}}</text>
<text class="full">{{we.formatTime(fullTime)}}</text>
</view>
<t-progress percentage="{{(currTime/fullTime) * 100}}" label="{{false}}" />
</view>
<view class="controls">
<view class="btn btn-mid">
<t-icon size="40rpx" prefix="icon" name="rewind-1" />
</view>
<view class="btn btn-large" bind:tap="toggle">
<t-icon wx:if="{{!isPlaying}}" size="48rpx" prefix="icon" name="play" />
<t-icon wx:else size="48rpx" prefix="icon" name="pause" />
</view>
<view class="btn btn-mid">
<t-icon size="40rpx" prefix="icon" name="rewind" />
</view>
</view>
</view>
<wxs module="we">
// 格式化时间展示
function formatTime(time) {
var sec = time % 60
sec = sec.toFixed(0)
if (sec < 10) sec = '0' + sec
var min = time / 60
min = min.toFixed(0)
if (min < 10) min = '0' + min
return min + ':' + sec
}
module.exports = {
formatTime: formatTime
}
</wxs>

View File

@ -0,0 +1,35 @@
.slider .time {
display: flex;
flex-direction: row;
justify-content: space-between;
color: #999999;
font-size: 22rpx;
}
.controls {
display: flex;
align-items: center;
justify-content: center;
}
.btn {
display: flex;
margin: 20rpx;
justify-content: center;
align-items: center;
background-color: #3c9cff;
color: #ffffff;
}
.btn-large {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
}
.btn-mid {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}

View File

@ -0,0 +1,76 @@
import network from "../../config/network";
// components/poem-audio/poem-audio.js
Component({
/**
* 组件的属性列表
*/
properties: {
audio: String,
lyric: String
},
/**
* 组件的初始数据
*/
data: {
audioCtx: null,
isPlaying: false,
fullTime: 0,
currTime: 0,
playListenerTimer: -1
},
/**
* 组件的方法列表
*/
methods: {
play() {
let audioCtx = this.data.audioCtx
// 检测是否存在Audio
if (audioCtx === null) {
console.log("不存在音频上下文,创建...");
audioCtx = wx.createInnerAudioContext()
audioCtx.src = network.backstageUrl + this.properties.audio
audioCtx.onEnded(() => this.setData({isPlaying: false, currTime: 0}))
this.setData({audioCtx})
}
audioCtx.play()
// 开始监听播放进度
if (this.data.playListenerTimer === -1) {
let timer = setInterval(() => {
if (this.data.isPlaying) {
this.setData({currTime: this.data.audioCtx.currentTime})
}
if (this.data.fullTime === 0) {
this.setData({fullTime: this.data.audioCtx.duration})
}
}, 500)
this.setData({playListenerTimer: timer})
}
this.setData({isPlaying: true})
},
pause() {
let audioCtx = this.data.audioCtx
if (audioCtx !== null) {
audioCtx.pause()
this.setData({isPlaying: false})
}
// 清空播放时间监听器
if (this.data.playListenerTimer !== -1) {
clearInterval(this.data.playListenerTimer)
this.setData({playListenerTimer: -1})
}
},
toggle() {
if (this.data.isPlaying) {
this.pause()
} else {
this.play()
}
},
},
})

View File

@ -0,0 +1,8 @@
{
"component": true,
"usingComponents": {
"t-icon": "tdesign-miniprogram/icon/icon",
"t-progress": "tdesign-miniprogram/progress/progress",
"audio-controls": "audio-controls/audio-controls"
}
}

View File

@ -0,0 +1,8 @@
<view class="poem-audio-container">
<view class="lyric-area">
</view>
<audio-controls currTime="{{currTime}}"
fullTime="{{fullTime}}"
isPlaying="{{isPlaying}}"
bind:toggle="toggle" />
</view>

View File

@ -0,0 +1,38 @@
.poem-audio-container {
padding: 30rpx;
}
.slider .time {
display: flex;
flex-direction: row;
justify-content: space-between;
color: #999999;
font-size: 22rpx;
}
.controls {
display: flex;
align-items: center;
justify-content: center;
}
.btn {
display: flex;
margin: 20rpx;
justify-content: center;
align-items: center;
background-color: #3c9cff;
color: #ffffff;
}
.btn-large {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
}
.btn-mid {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
}

View File

@ -1,10 +1,10 @@
@font-face {
font-family: 'icon';
src: url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.eot?3gxqgj');
src: url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.eot?3gxqgj#iefix') format('embedded-opentype'),
url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.ttf?3gxqgj') format('truetype'),
url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.woff?3gxqgj') format('woff'),
url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.svg?3gxqgj#icomoon') format('svg');
src: url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.eot?kp4sdg');
src: url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.eot?kp4sdg#iefix') format('embedded-opentype'),
url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.ttf?kp4sdg') format('truetype'),
url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.woff?kp4sdg') format('woff'),
url('https://a-1254429201.cos.ap-chengdu.myqcloud.com/poem-font/icomoon.svg?kp4sdg#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
@ -64,3 +64,6 @@
.icon-file-text:before {
content: "\e926";
}
.icon-pause:before {
content: "\e909";
}

View File

@ -3,6 +3,7 @@
"t-tabs": "tdesign-miniprogram/tabs/tabs",
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
"poem-content": "/components/poem-content/poem-content",
"poem-translate": "/components/poem-translate/poem-translate"
"poem-translate": "/components/poem-translate/poem-translate",
"poem-audio": "/components/poem-audio/poem-audio"
}
}

View File

@ -1,5 +1,5 @@
<view class="poem-detail-container">
<t-tabs default-value="{{0}}" sticky>
<t-tabs default-value="{{3}}" sticky swipeable="{{false}}">
<t-tab-panel label="诗词" value="0">
<poem-content poem="{{poem}}" author="{{author}}" blocks="{{blocks}}" />
</t-tab-panel>
@ -11,8 +11,8 @@
<view class="appreciation-block" wx:for="{{appreciation}}" wx:for-item="block">{{block}}</view>
</view>
</t-tab-panel>
<t-tab-panel label="朗读" value="3">
<t-tab-panel wx:if="{{poem.audio!==null}}" label="朗读" value="3">
<poem-audio audio="{{poem.audio}}" />
</t-tab-panel>
<t-tab-panel label="动画" value="4">