歌词滚动效果

需求

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

实现

1.准备数据

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

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

ini 复制代码
// 处理后端返回歌词
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标签

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

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

javascript 复制代码
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
        } 
}

计算偏移量

ini 复制代码
        // 计算偏移量 
        /**
         * 偏移量
         * @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时间触发计算偏移函数

less 复制代码
  // audio 时间变化事件
audio.addEventListener('timeupdate', Setoffset)
3.添加样式
xml 复制代码
<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);控制文字大小

css 复制代码
     .center-ci {
                transform: translateY(-50px);
                display: block;
                height: 100%;
                width: 100%;

                p {
                    transition: 0.2s;
                    font-size: 20px;
                    text-align: center;
                }

                .active {
                    transform: scale(1.2);
                    color: goldenrod;
                }
            }

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

ini 复制代码
// 根据偏移量滚动歌词 
lyricHeight.value.style.transform = `translateY(-${store.Offset}px)`
4.效果

~谢谢观看

相关推荐
熊的猫27 分钟前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
瑶琴AI前端1 小时前
uniapp组件实现省市区三级联动选择
java·前端·uni-app
会发光的猪。1 小时前
如何在vscode中安装git详细新手教程
前端·ide·git·vscode
mosen8681 小时前
Uniapp去除顶部导航栏-小程序、H5、APP适用
vue.js·微信小程序·小程序·uni-app·uniapp
别拿曾经看以后~2 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
我要洋人死2 小时前
导航栏及下拉菜单的实现
前端·css·css3
川石课堂软件测试2 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
科技探秘人2 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人2 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR2 小时前
前端开发中ES6的技术细节二
前端·javascript·es6