03_歌词滚动效果

03_歌词滚动效果


文章目录


效果

一、数据准备

①:歌词

js 复制代码
var lrc = `[00:00.95]夜微凉 - 徐珊
[00:01.9]词:周敏君/徐珊
[00:02.85]曲:秦天
[00:03.8]编曲:秦天
[00:04.75]制作人:秦天
[00:05.7]配唱制作人:孙依哲/李少成
[00:06.65]制作统筹:宋双喜
[00:07.6]财务及行政协力:周美军/赵杨
[00:08.55]监制:吕军/张斌/柴奇/古国远
[00:09.5]出品人:侯俊/张健
[00:10.45]出品监制:秦朗
[00:11.4]艺人经纪:徐真真
[00:12.35]封面设计:LDG
[00:13.35]夜微凉
[00:15.72]灯微暗
[00:18.12]远处的你
[00:19.62]却如此温暖
[00:22.92]如果再没有什么
[00:25.29]结果是我相信你
[00:27.99]会使
[00:29.22]我更加心安
[00:34.59]拥抱世界美丽
[00:37.02]此刻我想拥抱你
[00:39.42]如果再没有什么
[00:41.46]结果是我相信你
[00:44.22]会使我心
[00:45.54]更安静
[00:47.22]遇到烦心
[00:48.99]放于时间里慢慢说给你听
[00:57.42]会让你走出凹凸地 平线
[01:00.99]因为这自信
[01:02.85]让我更加情愿
[01:06.99]道路总是走走停停
[01:10.86]只是你还心有不安
[01:15.45]遇到烦心
[01:17.01]因为我不想让你看到
[01:20.22]看到我忧伤的表情
[01:24.99]放于时间里
[01:27.39]慢慢的说给你听
[01:30.09]稀释忧愁
[01:31.89]面对不安
[01:36.990005]拥抱世界美丽
[01:39.42]此刻我想拥抱你
[01:41.85]如果再没有什么
[01:43.86]结果是我相信你
[01:46.619995]会使我心
[01:47.94]更安静
[01:49.65]遇到烦心
[01:51.39]放于时间里慢慢说给你
[01:57.509995]夜微凉
[01:58.92]灯微暗
[02:01.29]远处的你
[02:02.79]却如此温暖
[02:06.06]如果再没有什么
[02:08.46]结果是我相信你
[02:11.22]会使
[02:12.42]我更加心安
[02:15.45]遇到烦心
[02:17.01]因为我不想让你看到
[02:20.22]看到我忧伤的表情
[02:24.95999]放于时间里
[02:27.39]慢慢的说给你听
[02:30.06]稀释忧愁
[02:31.89]面对不安
[02:34.59]拥抱世界美丽
[02:36.99]此刻我想拥抱你
[02:39.45]如果再没有什么
[02:41.45999]结果是我相信你
[02:44.22]会使我心
[02:45.54001]更安静
[02:47.22]遇到烦心
[02:48.99]放于时间里慢慢说给你听`

②:音频等

  • 资源在文章的顶部绑定

二、代码实现

①:首页

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>歌词滚动效果</title>
    <link rel="shortcut icon" href="./assets/favicon.ico" type="image/x-icon">
    <link rel="stylesheet" href="./css/index.css">
</head>
<body>
<audio controls src="./assets/夜微凉.mp3"></audio>
<div class="container">
    <ul class="lrc-list">
    </ul>
</div>
<script src="./js/data.js"></script>
<script src="./js/index.js"></script>

</body>
</html>

②:样式

css 复制代码
* {
    padding: 0;
    margin: 0;
}
body{
    background-color: black;
    color: #666;
    text-align: center;
}
audio{
    width: 450px;
    height: 50px;
    margin: 30px 0;
}
.container{
    height: 420px;
    overflow: hidden;
}
.container ul{
    transition: 0.5s;
    list-style: none;
}
.container li{
    height: 30px;
    line-height: 30px;
    transition: 0.2s;
}
.container .lrc-list .active{
    color: #fff;
    transform: scale(1.3);
}

③:js逻辑

js 复制代码
/**
 * 解析歌词字符串 得到每个歌词的对象
 * {time: 开始时间, words: 歌词内容}
 */
var lrcArray = [];

function parseLrc() {
    let lines = lrc.split("\n");
    lines.forEach(item => {
        let parts = item.split("]");
        var timeStr = parts[0].substr(1);
        let time = parseTime(timeStr);
        var obj = {
            time: time,
            words: parts[1]
        }
        lrcArray.push(obj);
    })
    return lrcArray;
}

/**
 * 获取需要的dom
 */
var dom = {
    audio: document.querySelector("audio"),
    ul: document.querySelector('.container ul'),
    container: document.querySelector('.container'),
}

/**
 * 将字符串转成时间数字 01:02.85 ==> 1*60 + 2.85(秒)
 * @param timeStr 时间字符串
 */
function parseTime(timeStr) {
    let split = timeStr.split(":");
    return +split[0] * 60 + +split[1]
}

/**
 * 计算出,在当前播放器播放到几秒的情况下
 * lrcArray 数组中 应该高亮显示的歌词下标
 * -1 没有任何一句歌词需要显示
 */
function findIndex() {
    // 播放器当前时间
    let time = dom.audio.currentTime;
    for (let i = 0; i < lrcArray.length; i++) {
        if (lrcArray[i].time > time) {
            return i - 1
        }
    }
    // 如果大于最后一句歌词时间 显示最后一句歌词
    return lrcArray.length - 1
}

console.log(parseLrc());


/**
 * 创建歌词元素 li
 */
function createLrcElements(){
    lrcArray.forEach(item =>{
        var li = document.createElement("li");
        li.textContent = item.words
        dom.ul.appendChild(li)
    })
}
createLrcElements()

// 容器的高度
let containerHeight = dom.container.clientHeight;
// 每一个li的高度
let liHeight = dom.ul.children[0].clientHeight;
// 最大便宜量
let max = dom.ul.clientHeight - containerHeight;

/**
 * 设置ul的偏移量
 */
function setOffset() {
    let index = findIndex();
    let h1 = liHeight * index + liHeight / 2 - containerHeight / 2
    if (h1 < 0){
        h1 = 0
    }
    if (h1 > max){
        h1 = max
    }
    // 去掉之前的 active 样式
    let li = dom.ul.querySelector('.active');
    if (li){
        li.classList.remove('active')
    }

    dom.ul.style.transform = `translateY(-${h1}px)`
    li = dom.ul.children[index];
    if (li){
        li.classList.add('active')
    }
}
dom.audio.addEventListener('timeupdate', () => setOffset())

④:测试

相关推荐
理想不理想v9 分钟前
vue经典前端面试题
前端·javascript·vue.js
不收藏找不到我10 分钟前
浏览器交互事件汇总
前端·交互
YBN娜24 分钟前
Vue实现登录功能
前端·javascript·vue.js
阳光开朗大男孩 = ̄ω ̄=24 分钟前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
minDuck28 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
小政爱学习!1 小时前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。1 小时前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
花花鱼1 小时前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
k09331 小时前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
EricWang13581 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端