注册
web

歌词滚动效果

需求


实现歌词滚动效果,类似网易云音乐播放界面。



实现


1.准备数据

后台一般会返回这样一个歌词数据,每个时间都对应当前这个歌词。



因为是字符串不方便直接使用,我们把他转化为对象格式。封装一个utils工具传入歌词把lyric转化为对象。


// 处理后端返回歌词
export const HandleLyric = (lyric) => {
    function convertToSeconds(timeArray) {
        // 获取分钟和秒(包括毫秒)  
        const minutes = parseFloat(timeArray[0]); // 使用parseFloat来确保即使分钟有小数部分也能正确处理  
        const secondsWithMilliseconds = parseFloat(timeArray[1]);
        // 计算总秒数  
        const totalSeconds = minutes * 60 + secondsWithMilliseconds;
        return totalSeconds;
    }
    let line = lyric.split('\n')
    let value1 = []
    for (let i = 0; i < line.length; i++) {
        let str = line[i]
        // 把字符串分割为数组
        let part = str.split(']')
        let timestr = part[0].substring(1)
        let parts = timestr.split(':')
        let obj = {
            time: convertToSeconds(parts),
            word: part[1]
        }
        value1.push(obj)
    }
    return value1
}


2.计算偏移量

准备audio标签


  <div class="audio">
      <el-button>立即播放/暂停</el-button>
      <audio :src="audio_info['url']" ref="audio" class="audio-sty">11</audio>
  </div>

调用audio标签的currentTime可以获取当前歌曲播放到第几秒,遍历歌词的时间和当前时间(currentTime)比较,返回的i就是当前歌词的在第几行。


const changeplay = () => {
    let audio = document.querySelector('.audio-sty')
     // 找到当前这一句歌词的索引
        function FindIndex() {
            let currentTime = audio.currentTime
            for (var i = 0; i < store.lyicWords.length; i++) {
                if (currentTime < store.lyicWords[i].time) {
                    return i - 1
                }
            }
            return store.lyicWords.length - 1
        } 
}

计算偏移量


        // 计算偏移量 
        /**
         * 偏移量
         * @containerHeight //容器高度
         * @PHeight   //单个歌词高度
         */
        function Setoffset() {
            var index = FindIndex()
            var offset = index * store.PHeight + store.PHeight / 2 - store.containerHeight / 2
            if (offset < 0) {
                offset = 0
            }
            store.index = index
            store.Offset = offset
        }


用当前歌词所偏移的大小加上单个歌词Height1/2的大小,就可以实现歌词偏移,如果想让每次高亮的歌词在中间,需要再减去container盒子自身Height的一半。




调用audio的timeupadte时间触发计算偏移函数


  // audio 时间变化事件
audio.addEventListener('timeupdate', Setoffset)

3.添加样式

<div class="center" ref="center">
            <h1>歌词</h1>
<el-card class="box-center">
      <div class="center-ci" style="overflow: auto;" ref="lyricHeight">
      <p v-for="(item, index) in  songList['txt']" v-if="songList['txt'].length != 0"
                        :class="[index == store.index ? 'active' : '']">
{{item }}</p>
       <p v-else>纯音乐,无歌词</p>
       </div>
</el-card>
</div>

使用transform: translateY(-50px);控制偏移

使用transform: scale(1.2);控制文字大小


     .center-ci {
                transformtranslateY(-50px);
                display: block;
                height100%;
                width100%;

                p {
                    transition0.2s;
                    font-size20px;
                    text-align: center;
                }

                .active {
                    transformscale(1.2);
                    color: goldenrod;
                }
            }

给歌词容器设置transform就可以实现歌词偏移了



// 根据偏移量滚动歌词 
lyricHeight.value.style.transform = `translateY(-${store.Offset}px)`

4.效果


~谢谢观看


作者:remember_me
来源:juejin.cn/post/7336538738749849600

0 个评论

要回复文章请先登录注册