import React, { useState, useEffect, useRef } from 'react';
import './AudioPlayer.css'; // 请确保样式文件正确链接
const AudioPlayer = () => {
const audioRef = useRef(null);
const textContentRef = useRef(null);
const [currentLineIndex, setCurrentLineIndex] = useState(-1);
const [currentTime, setCurrentTime] = useState(0);
// 模拟的音频文稿数据,每一条数据包括开始时间和对应的文本
const transcript = [
{ 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 onTimeUpdate = () => {
setCurrentTime(audioRef.current.currentTime);
updateHighlightedText();
};
// 音频结束时处理
const onEnded = () => {
setCurrentLineIndex(-1); // 播放结束时,取消高亮
};
// 更新高亮文本
const updateHighlightedText = () => {
const lineIndex = transcript.findIndex(
(item, index) =>
currentTime >= item.time && (index + 1 === transcript.length || currentTime < transcript[index + 1].time)
);
if (lineIndex !== -1 && lineIndex !== currentLineIndex) {
setCurrentLineIndex(lineIndex);
scrollToCurrentLine();
}
};
// 判断当前行是否需要高亮
const isHighlighted = (index) => index === currentLineIndex;
// 获取文本行的样式,用于高亮显示
const getTextStyle = (index) => {
if (index === currentLineIndex) {
return { fontWeight: 'bold', color: 'red' }; // 高亮样式
}
return {};
};
// 滚动到当前高亮的文本行
const scrollToCurrentLine = () => {
const currentLine = textContentRef.current?.children[currentLineIndex];
if (currentLine) {
currentLine.scrollIntoView({
behavior: 'smooth',
block: 'end',
});
}
};
// 音频开始播放时,初始化时间和高亮
useEffect(() => {
if (audioRef.current) {
audioRef.current.currentTime = 0; // 初始化音频播放时间
}
setCurrentLineIndex(-1); // 默认无高亮
}, []);
return (
<div className="audio-player">
<audio
ref={audioRef}
style={{ width: '500px' }}
onTimeUpdate={onTimeUpdate}
onEnded={onEnded}
controls
>
<source src="./assets/C400000mH3kk2V2iiK.mp4" type="audio/mp3" />
</audio>
<div className="text-content" ref={textContentRef}>
{transcript.map((line, index) => (
<p
key={index}
className={isHighlighted(index) ? 'highlighted' : ''}
style={getTextStyle(index)}
>
{line.text}
</p>
))}
</div>
</div>
);
};
export default AudioPlayer;
audioplays.css
.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;
}