音频联动-react

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猛男敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值