hookehuyr

🐞 fix: 音频组件代码整理

......@@ -8,10 +8,6 @@
<van-icon @click="onClose" name="cross" color="#DD7850" size="1.25rem" />
</div>
</template>
<!-- <page-info ref="pageInfo" :info="itemInfo" :height="info_height" @close-float="onCloseFloat" @route="onRoute"></page-info> -->
<!-- <div v-if="showClose" @click="closeFloatPanel" class="close-float-panel">
<van-icon name="arrow-left" color="#FFF" size="1.5rem" />
</div> -->
<div class="van-hairline--top" style="padding: 1rem;">
<div v-for="(item, index) in audio_list" :key="index" class="van-hairline--bottom audio-item">
<div :class="['point', audio_index === index ? 'checked' : '']"></div>
......@@ -19,15 +15,11 @@
{{ index + 1 }}. {{ item.title }}<span v-if="item.play" class="text-center">正在播放</span>
</div>
<!-- <div style="border: 1px solid #DD7850; border-radius: 50%; padding: 0.25rem;">
<van-icon v-if="audio_index === index" name="https://cdn.ipadbiz.cn/xys/map/%E6%92%AD%E6%94%BE@2x.png" size="1.75rem" />
<van-icon v-else name="https://cdn.ipadbiz.cn/xys/map/%E6%92%AD%E6%94%BE%E6%9A%82%E5%81%9C@2x.png" size="1.75rem" />
</div> -->
<div class="progress-ring">
<div class="circle">
<div class="pause-icon">
<van-icon @click="handleAudioPause(item, index)" v-if="item.play" name="https://cdn.ipadbiz.cn/xys/map/%E6%92%AD%E6%94%BE@2x.png" size="2.25rem" />
<van-icon @click="handleAudioPlay(item, index)" v-else name="https://cdn.ipadbiz.cn/xys/map/%E6%92%AD%E6%94%BE%E6%9A%82%E5%81%9C@2x.png" size="2.25rem" />
<van-icon @click="handleAudioPause(item, index)" v-if="item.play" name="https://cdn.ipadbiz.cn/bieyuan/map/icon/pauseButton@3x.png" size="2.05rem" />
<van-icon @click="handleAudioPlay(item, index)" v-else name="https://cdn.ipadbiz.cn/bieyuan/map/icon/play@3x.png" size="2.05rem" />
</div>
<div :class="['progress', item.play ? 'checked' : '']"></div>
</div>
......@@ -43,9 +35,15 @@
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router';
import $ from 'jquery';
import { storeToRefs } from 'pinia'
import { mainStore } from '@/store';
const store = mainStore();
const { audio_status, audio_entity } = storeToRefs(store);
const props = defineProps({
height: Number,
status: String,
});
const themeVars = ref({
......@@ -55,23 +53,32 @@ const themeVars = ref({
const anchors = ref([0, (0.2 * window.innerHeight), (0.5 * window.innerHeight)]);
const onHeightChange = ({ height }) => {
if (!height) {
onClose()
const onHeightChange = ({ height }) => { // 监听高度变化
if (!height) { // 关闭
onClose();
}
}
const info_height = ref(0);
watch(
() => props.height,
(v) => {
info_height.value = v;
}
)
const onClose = () => {
audio.value.pause();
// watch(
// () => props.status,
// (v) => {
// if (v) { // 监听详情页播放状态,关闭浮层音频播放
// }
// }
// )
const onClose = () => { // 关闭列表回调
audio.value.pause(); // 暂停音频播放
pauseProgress();
// 播放进度条
$('.progress').css('background', 'conic-gradient(#f07142 0%, transparent 0%)');
......@@ -79,7 +86,7 @@ const onClose = () => {
emit('close');
}
const emit = defineEmits(['close']);
const emit = defineEmits(['close', 'status']);
const audio_index = ref();
......@@ -103,114 +110,135 @@ onMounted(() => {
play: false
},
];
let audioDuration = 60; // 音频总时长 (秒)
let elapsedTime = 0; // 已播放的时间
// nextTick(() => {
// setPlayProgress(30)
// })
});
/**
* 音频播放模块
*/
const audio = ref(new Audio());
const duration = ref(0); // 音频总时长
const currentTime = ref(0); // 当前播放时间
// let audioDuration = 30; // 音频总时长 (秒)
// const currentTime = ref(0); // 当前播放时间
let elapsedTime = 0; // 已播放的时间
let intervalId = null; // 保存setInterval的ID
// 函数:更新进度条
function updateProgress(audioDuration, index) {
/**
* 更新进度条
*/
const updateProgress = (audioDuration, index) => {
let progressPercent = (elapsedTime / audioDuration) * 100;
document.querySelector('.progress.checked').style.background =
`conic-gradient(#f07142 ${progressPercent}%, transparent ${progressPercent}%)`;
if (elapsedTime >= audioDuration) {
clearInterval(intervalId); // 音频播放完成,停止更新
pauseProgress(); // 音频播放完成,停止更新
// 切换到下一个音频
let idx = index + 1;
if (idx >= audio_list.value.length) {
idx = 0;
}
handleAudioPlay(audio_list.value[idx], idx)
// 播放下一个音频
handleAudioPlay(audio_list.value[idx], idx);
}
}
// 函数:启动进度更新
function startProgress(audioDuration, index) {
/**
* 启动进度更新
*/
const startProgress = (audioDuration, index) => {
intervalId = setInterval(() => {
elapsedTime++;
updateProgress(audioDuration, index);
}, 1000);
}
// 函数:暂停进度更新
function pauseProgress() {
/**
* 暂停进度更新
*/
const pauseProgress = () => {
clearInterval(intervalId);
}
// 初始化进度条
// startProgress();
// const handleAudio = (item, index) => {
// audio_index.value = index;
// document.querySelector('.progress').style.background =
// `conic-gradient(#f07142 0%, transparent 0%)`;
// clearInterval(progressInterval); // 音频播放完成
// setPlayProgress(item.duration);
// }
/**
* 暂停播放回调
* @param item
* @param index
*/
const handleAudioPause = (item, index) => {
item.play = false;
audio.value.pause();
pauseProgress();
item.play = false; // 更新播放状态
audio.value.pause(); // 暂停音频播放
pauseProgress(); // 暂停进度更新
}
const updateDuration = () => {
duration.value = Math.floor(audio.value.duration); // 获取音频时长
};
const updateTime = () => {
currentTime.value = Math.floor(audio.value.currentTime); // 获取当前播放时间
};
// const updateTime = () => {
// currentTime.value = Math.floor(audio.value.currentTime); // 获取当前播放时间
// };
// 监听 'loadedmetadata' 事件,确保在音频元数据加载后获取时长
audio.value.addEventListener('loadedmetadata', updateDuration);
// 监听 'timeupdate' 事件,实时更新当前播放时间
audio.value.addEventListener('timeupdate', updateTime);
// audio.value.addEventListener('timeupdate', updateTime);
/*********************************** END *************************************/
/**
* 播放音频回调
* @param item
* @param index
*/
const handleAudioPlay = (item, index) => {
// 播放状态
audio_list.value.forEach(item => item.play = false);
audio_list.value.forEach(item => item.play = false); // 清空播放状态
if (audio_index.value !== index) {
audio.value.src = item.src;
}
// 播放进度条
$('.progress').css('background', 'conic-gradient(#f07142 0%, transparent 0%)')
clearInterval(intervalId);
// 后台有播放器运行时,先暂停
if (audio_status.value === 'play'){
audio_entity.value.pause();
}
$('.progress').css('background', 'conic-gradient(#f07142 0%, transparent 0%)'); // 清空进度条
pauseProgress(); // 暂停进度更新
let play_status = audio.value.play() // 播放
if (play_status) {
play_status.then(() => {
item.play = true;
// 存放到pinia里面控制
// store.changeAudio(audio.value);
// store.changeAudioSrc(audio.value.src);
// store.changeAudioStatus('play');
store.changeAudio(audio.value);
store.changeAudioSrc(audio.value.src);
store.changeAudioStatus('play');
//
startProgress(duration.value, index);
if (audio_index.value === index) { // 点击同一音频
} else {
startProgress(duration.value, index); // 开始更新进度
if (audio_index.value !== index) { // 点击非同一音频
audio_index.value = index;
elapsedTime = 0
elapsedTime = 0; // 重置已播放时间
}
emit('status', 'play');
}).catch((e) => {
// 失败
console.log('Operation is too fast, audio play fails')
})
}
}
const voicePause = () => {
audio.value.pause();
pauseProgress(); // 暂停进度更新
store.changeAudioStatus('pause');
}
watch(
() => audio_status.value,
(v) => {
if (v === 'pause') {
voicePause();
audio_list.value.forEach(item => item.play = false);
}
},
{ immediate: true }
);
</script>
<style lang="less" scoped>
......
<!--
* @Date: 2024-09-15 22:08:49
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-10-08 17:37:42
* @LastEditTime: 2024-10-09 11:06:12
* @FilePath: /map-demo/src/views/bieyuan/info.vue
* @Description: 文件描述
-->
......@@ -80,7 +80,7 @@
<van-back-top />
<audio-play-list :height="audio_list_height" @close="onCloseAudioList"></audio-play-list>
<audio-play-list :height="audio_list_height" :status="audio_status" @close="onCloseAudioList" @status="onStatusAudioList"></audio-play-list>
</div>
</template>
......@@ -135,22 +135,22 @@ const images = ref([
const active = ref(0);
const play_audio_index = ref(null);
const audioList = ref([{
text: '5分钟观呼吸',
src: 'https://cdn.ipadbiz.cn/bieyuan/map/audio/%E6%AD%A3%E5%BF%B5%E5%91%BC%E5%90%B8%EF%BC%8810%E5%88%86%E9%92%9F%EF%BC%89.mp3',
play: false,
}, {
text: '10分钟正念静坐',
src: 'https://cdn.ipadbiz.cn/bieyuan/map/audio/%E5%8D%81%E5%88%86%E9%92%9F%E6%AD%A3%E5%BF%B5%E9%9D%99%E5%9D%9020210510.mp3',
play: false,
}, {
text: '15分钟正念静坐',
src: 'https://cdn.ipadbiz.cn/bieyuan/map/audio/%E5%8D%81%E5%88%86%E9%92%9F%E6%AD%A3%E5%BF%B5%E9%9D%99%E5%9D%9020210510.mp3',
play: false,
}])
// const audioList = ref([{
// text: '5分钟观呼吸',
// src: 'https://cdn.ipadbiz.cn/bieyuan/map/audio/%E6%AD%A3%E5%BF%B5%E5%91%BC%E5%90%B8%EF%BC%8810%E5%88%86%E9%92%9F%EF%BC%89.mp3',
// play: false,
// }, {
// text: '10分钟正念静坐',
// src: 'https://cdn.ipadbiz.cn/bieyuan/map/audio/%E5%8D%81%E5%88%86%E9%92%9F%E6%AD%A3%E5%BF%B5%E9%9D%99%E5%9D%9020210510.mp3',
// play: false,
// }, {
// text: '15分钟正念静坐',
// src: 'https://cdn.ipadbiz.cn/bieyuan/map/audio/%E5%8D%81%E5%88%86%E9%92%9F%E6%AD%A3%E5%BF%B5%E9%9D%99%E5%9D%9020210510.mp3',
// play: false,
// }])
const playAudio = (item, index) => {
audioList.value.forEach(item => item.play = false);
page_details.value.experience_audio.forEach(item => item.play = false);
audio.value.src = item.src;
// 后台有播放器运行时,先暂停
if (audio_status.value === 'play'){
......@@ -159,9 +159,7 @@ const playAudio = (item, index) => {
play_audio_index.value = index;
let play_status = audio.value.play() // 播放
if (play_status) {
console.warn('start');
play_status.then(() => {
console.warn('success');
item.play = true;
// 存放到pinia里面控制
store.changeAudio(audio.value);
......@@ -317,7 +315,7 @@ watch(
(v) => {
if (v === 'pause') {
voicePause();
audioList.value.forEach(item => item.play = false);
page_details.value.experience_audio?.forEach(item => item.play = false);
}
},
{ immediate: true }
......@@ -370,6 +368,13 @@ const onClickAudioList = () => {
const onCloseAudioList = () => {
audio_list_height.value = 0;
}
const onStatusAudioList = (status) => { // 音频列表组件,状态改变
page_details.value.experience_audio?.forEach(item => item.play = false);
audio.value.pause();
play_audio_index.value = null;
store.changeAudioStatus('pause');
}
</script>
<style lang="less">
......