播放音频,内容可根据时间来定位滚动位置(使用element-ui时间线组件)定义div高度
<div class="timeline-container"
ref="timelineContainer">
<TimeLine :events="events"
ref="timeline" />
</div>
<audio :key="audioSourceKey"
ref="audioPlayer"
controls
autoplay
@play="startAutoScroll"
@pause="stopAutoScroll">
<source :src="audioSource">
</audio>
</div>
.timeline-container {
max-height: 430px;
overflow-y: auto;
padding-right: 10px;
}
evens是json类型
color: "#3d9ffe"
content: "喂,你好。"
icon: "el-icon-user-solid"
size: "large"
timeSec: 7
timestamp: "【用户 1】 00:00:07"
timeSec为录音开始时间,等下以此为基准与播放关联
播放启动时调用startAutoScroll方法
startAutoScroll(){
if (this.scrollAnimation) return; // 防止多次调用
const audio = this.$refs.audioPlayer;
const timelineContainer = this.$refs.timelineContainer;
//获取每个元素
const timelineItems = this.$refs.timeline.$el.querySelectorAll(".el-timeline-item");
const animateScroll = () => {
if (!audio || audio.paused) return; // 如果音频暂停,则停止动画
const currentTime = Math.floor(audio.currentTime); // 取整,防止小数误差
// 1️、**找到录音中时间戳<=当前时间戳的最大值**
let validEvents = this.events.filter(event => event.timeSec <= currentTime); // 找到所有时间戳小于等于当前时间的对象
let maxTimeSec = Math.max(...validEvents.map(event => event.timeSec)); // 取最大值
// 2️、**获取所有与最大时间戳相等匹配的索引**(可获取到时间相同获取多个)
let indices = this.events
.map((event, index) => (event.timeSec === maxTimeSec ? index : -1))
.filter(index => index !== -1);
// 3、**先移除所有高亮**
timelineItems.forEach(item => item.classList.remove('highlight'));
// 4、**高亮所有匹配的事件**
indices.forEach(index => {
if (timelineItems[index]) {
timelineItems[index].classList.add('highlight');
}
});
// 5、**滚动匹配元素设置滚动高度**
const lastIndex = indices[0];
if (timelineItems[lastIndex]) {
timelineContainer.scrollTo({
top: timelineItems[lastIndex].offsetTop - (timelineContainer.clientHeight / 2) + (timelineItems[lastIndex].offsetHeight / 2),
behavior: "smooth",
});
}
this.scrollAnimation = requestAnimationFrame(animateScroll); // 继续下一帧
};
this.scrollAnimation = requestAnimationFrame(animateScroll);
},
// 停止滚动
stopAutoScroll () {
const timelineItems = this.$refs.timeline.$el.querySelectorAll(".el-timeline-item");
if (this.scrollAnimation) {
cancelAnimationFrame(this.scrollAnimation);
this.scrollAnimation = null;
//停止移除高亮
timelineItems.forEach(item => item.classList.remove('highlight'));
}
},
效果: