• React歌词滚动效果(跟随音乐播放时间滚动)


    首先给audio绑定更新时间事件

    1. const updateTime = e => {
    2. console.log(e.target.currentTime)
    3. setCurrentTime(e.target.currentTime);
    4. };
    5. <audio
    6. src={currentSong.url}
    7. ref={audio}
    8. onCanPlay={ready}
    9. onEnded={end}
    10. onTimeUpdate={updateTime}
    11. ></audio>

    当歌曲播放时间改变的时候会触发updateTime事件,如下所示

    歌词json格式

    1. [
    2. {
    3. "time": 2,
    4. "content": "采样曲:願い~あの頃のキミへ~",
    5. "contents": [
    6. "采样曲:願い~あの頃のキミへ~"
    7. ]
    8. },
    9. {
    10. "time": 12,
    11. "content": "中文填词:一只然",
    12. "contents": [
    13. "中文填词:一只然"
    14. ]
    15. },
    16. {
    17. "time": 15,
    18. "content": "OP(原属词曲版权公司):テレビ東京ミュージック 东京电视台音乐",
    19. "contents": [
    20. "OP(原属词曲版权公司):テレビ東京ミュージック 东京电视台音乐"
    21. ]
    22. },
    23. {
    24. "time": 19,
    25. "content": "本作品经过原词曲作者以及版权公司授权",
    26. "contents": [
    27. "本作品经过原词曲作者以及版权公司授权"
    28. ]
    29. },
    30. ......
    31. ]

    接下来就是根据当前的播放时间显示歌词高亮,给歌词绑定高亮放大样式

    1. .highlight {
    2. color: $theme-color;
    3. font-weight: $font-weight-bold;
    4. font-size: 16px !important;
    5. }
    1. // 使用Redux的useSelector获取当前播放时间
    2. const currentTime = useSelector(state => state.musicReducer.currentTime);
    3. // 使用React的useMemo优化性能,只有当currentTime变化时,才会重新计算time的值
    4. const time= useMemo(() => {
    5. return currentTime;
    6. },[currentTime]);
    7. // updateTime函数用于更新当前歌词的索引
    8. const updateTime = e => {
    9. // 在所有歌词中找到第一个时间大于当前播放时间的歌词,其前一个歌词就是当前应该显示的歌词
    10. const currentLyricIndex = lyric.findIndex((lyricItem, index) => {
    11. // 判断是否是最后一项歌词,如果是,下一项歌词的时间设为无穷大
    12. const isLastItem = index === lyric.length - 1;
    13. const nextLyricTime = isLastItem ? Infinity : lyric[index + 1].time;
    14. // 如果当前播放时间在当前歌词和下一条歌词的时间之间,说明当前歌词应该被显示
    15. return time >= lyricItem.time && time < nextLyricTime;
    16. });
    17. // 更新当前歌词的索引
    18. setCurrentLyricIndex(currentLyricIndex);
    19. };
    20. // 使用React的useEffect在time变化时,调用updateTime函数,更新当前歌词的索引
    21. useEffect(() => {
    22. updateTime()
    23. }, [time]);

     当time发生变化时,调用updateTime函数来更新当前歌词的索引currentLyricIndex。确保在歌曲播放过程中,歌词随着时间的推移而更新。

    最后,实现歌词滚动的效果

    1. 创建 scrollRef

      const scrollRef = useRef();

      使用 useRef 创建了一个 scrollRef,用于引用 Scroll 组件的实例。

    2. 使用 useEffect 进行歌词滚动:

      1. useEffect(() => {
      2. // 模拟异步加载歌词
      3. // 假设你要滚动到的歌词元素有一个特定的类名 ".lyric-item.highlight"
      4. const selector = '.lyric-item.highlight';
      5. // 调用 Scroll 组件的 scrollToElement 方法
      6. if (scrollRef.current) {
      7. scrollRef.current.scrollToElement(selector, 500); // 第二个参数是滚动时间,可以根据需要调整
      8. }
      9. }, [currentLyricIndex]);

      currentLyricIndex 发生变化时,useEffect 会被触发。在该效果中,它模拟异步加载歌词,然后通过 scrollRef.current.scrollToElement 方法滚动到指定的歌词元素,滚动时间为500毫秒。这样,每次歌词发生变化时都会滚动到当前高亮的歌词位置。

    3. Scroll 组件的 scrollToElement 方法实现:

      1. scrollToElement(selector, time = 0) {
      2. if (bScroll) {
      3. const targetElement = document.querySelector(selector);
      4. if (targetElement) {
      5. const containerHeight = scrollContainerRef.current.clientHeight;
      6. const targetHeight = targetElement.clientHeight;
      7. const offsetTop = (containerHeight - targetHeight) / 2;
      8. bScroll.scrollToElement(targetElement, time, 0, -offsetTop);
      9. }
      10. }
      11. }

      这是 Scroll 组件内部的 scrollToElement 方法的实现。首先,通过 document.querySelector(selector) 获取到目标元素(具有指定类名的高亮歌词元素)。然后,计算目标元素相对于滚动容器的偏移,最后使用 bScroll.scrollToElement 将目标元素滚动到可视区域,传入的参数包括时间、水平和垂直的偏移。

  • 相关阅读:
    CSRF(Steam的链接不用随便点)
    【SQL】MySQL中的SQL优化、explain执行计划
    Java案例:打印折纸的次数
    Java中的多线程如何理解——精简
    管理文件系统
    Java反射的详细解析之三
    flask框架-[实现websocket]:将socketio处理函数部分集中管理,使用类的方式来管理,集中管理socketio处理函数
    liteos连接器脚本隐藏的指针问题
    数位DP day45
    【图像修复】基于改进的Criminisi算法实现图像修复附matlab代码
  • 原文地址:https://blog.csdn.net/weixin_51526447/article/details/136282481