<template>
<div class="audio-player">
<audio style="width: 500px;" ref="audio" @timeupdate="onTimeUpdate" @ended="onEnded" controls>
<source src="./assets/C400000mH3kk2V2iiK.mp4" type="audio/mp3" />
</audio>
<div class="text-content" ref="textContent">
<p
v-for="(line, index) in transcript"
:key="index"
:class="{'highlighted': isHighlighted(index)}"
:style="getTextStyle(index)"
>
{{ line.text }}
</p>
</div>
</div>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue';
const audio = ref(null);
const textContent = ref(null);
// 模拟的音频文稿数据,每一条数据包括开始时间和对应的文本
const transcript = ref([
{ time: 0, text: "欢迎来到这个音频播放器。" },
{ time: 4, text: "在接下来的几分钟里,我们将展示如何使用 Vue 3 构建一个动态音频播放器。" },
{ time: 10, text: "这里会展示更多的文本内容,它会随着音频的进度高亮显示。" },
{ time: 16, text: "每一行文本都会在音频的播放过程中相应的高亮,并且文本会自动滚动。" },
{ time: 22, text: "感谢您的收听,希望您享受这个简单的示范。" },
{ time: 25, text: "每一行文本都会在音频的播放过程中相应的高亮。" },
{ time: 30, text: "此处展示音频播放的不同段落,每个段落会在时间进度上有所不同。" },
{ time: 35, text: "当音频播放到指定时间时,文本会自动高亮显示,帮助用户跟踪当前播放的内容。" },
{ time: 42, text: "确保音频播放器中的所有文本都能正确显示,并随着播放进度同步。" },
{ time: 50, text: "如果你希望增加更多的功能,可以尝试加入音量控制、快进和倒退等选项。" },
{ time: 56, text: "我们将继续添加更多功能以增强用户体验。" },
{ time: 60, text: "感谢您的收听,以上就是本次音频播放的内容。" },
{ time: 65, text: "如果您有任何问题,可以随时联系我们的客服团队。" },
{ time: 70, text: "本音频播放结束,感谢您的使用。" },
{ time: 75, text: "接下来的演示会展示如何控制音频播放器的播放速率。" },
{ time: 80, text: "用户可以通过调整播放速率,让音频播放更慢或更快。" },
{ time: 85, text: "这种控制功能为用户提供了更灵活的播放体验。" },
{ time: 90, text: "如果您希望控制播放列表的顺序,可以尝试添加排序功能。" },
{ time: 95, text: "音频播放器还支持无限循环播放和随机播放功能,满足各种需求。" },
{ time: 100, text: "在下次更新中,我们计划加入新的音频格式支持。" },
{ time: 105, text: "感谢您与我们一同探索音频播放器的更多功能。" },
{ time: 110, text: "请继续关注我们未来的更新,期待更多精彩内容。" },
{ time: 115, text: "这次演示到此结束,祝您有一个愉快的一天!" }
]);
const currentLineIndex = ref(-1); // 当前高亮行的索引
const currentTime = ref(0);
// 更新播放进度
const onTimeUpdate = () => {
currentTime.value = audio.value.currentTime;
updateHighlightedText();
};
// 音频结束时处理
const onEnded = () => {
currentLineIndex.value = -1; // 播放结束时,取消高亮
};
// 更新高亮文本
const updateHighlightedText = () => {
const lineIndex = transcript.value.findIndex(
(item, index) =>
currentTime.value >= item.time && (index + 1 === transcript.value.length || currentTime.value < transcript.value[index + 1].time)
);
if (lineIndex !== -1 && lineIndex !== currentLineIndex.value) {
currentLineIndex.value = lineIndex;
scrollToCurrentLine();
}
};
// 判断当前行是否需要高亮
const isHighlighted = (index) => index === currentLineIndex.value;
// 获取文本行的样式,用于高亮显示
const getTextStyle = (index) => {
if (index === currentLineIndex.value) {
return { fontWeight: 'bold', color: 'red' }; // 高亮样式
}
return {};
};
// 滚动到当前高亮的文本行
const scrollToCurrentLine = () => {
const currentLine = textContent.value?.children[currentLineIndex.value];
if (currentLine) {
currentLine.scrollIntoView({
behavior: 'smooth',
block: 'end',
});
}
};
// 音频开始播放时,初始化时间和高亮
onMounted(() => {
audio.value.currentTime = 0; // 初始化音频播放时间
currentLineIndex.value = -1; // 默认无高亮
});
</script>
<style scoped>
.audio-player {
max-width: 600px;
margin: 0 auto;
}
.text-content {
max-height: 300px;
overflow-y: auto;
padding: 10px;
margin-top: 20px;
}
.text-content p {
margin: 10px 0;
font-size: 18px;
transition: color 0.3s ease, font-weight 0.3s ease;
}
.highlighted {
color: red;
font-weight: bold;
}
</style>