原生实现歌词和音乐滚动播放(同步有问题)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100svh;
        }

        .music {
            width: 300px;
            height: 40vh;
            overflow-y: hidden;
            display: grid;
            grid-template-columns: 1fr;
            position: relative;
        }

        .music::-webkit-scrollbar {
            display: none;
        }

        .music__wrapper {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: flex-start;
            font-size: 16px;
            line-height: 30px;
            position: absolute;
            top: 50%;
            width: 100%;
            height: 100%;
            transition: all 1s linear;
        }

        .music__wrapper span {
            background: linear-gradient(90deg, red 50%, #000 50%);
            background-size: 200% auto;
            background-position-x: -100%;
            background-clip: text;
            color: transparent;

        }

        .music__wrapper span.active {
            font-weight: bold;
            color: red;
        }
    </style>

</head>

<body>
    <div>
        <input type="text" oninput="getChange(this)">
        <button onclick="loadMusic()">加载</button>
    </div>
    <audio id="audio" controls></audio>
    <div class="music">
        <div class="music__wrapper">
        </div>
    </div>

    <script>

        function getChange(e) {
            music.musicId = e.value;
        }

        function loadMusic() {
            music.getMusic()
            music.getLyrics()
        }
        class Music {
            constructor(dom, audio) {
                this.musicDOM = document.querySelector(dom)
                this.audio = document.querySelector(audio)
                this.musicId = 1297802566;
                this.LyricesArr = [];
                this.status = "pause"
                this.audio.addEventListener("play", this.play.bind(this));
                this.audio.addEventListener("timeupdate", this.timeupdate.bind(this))
                this.audio.addEventListener("pause", this.pause.bind(this))
            }
            // 监听audio开始事件
            play(e) {
                this.status = "play"
                this.animate?.play()
            }
            // 监听audio暂停事件
            pause(e) {
                this.status = "pause"
                this.animate?.pause()

            }
            // 监听audio进度事件
            timeupdate(e) {
                const currentTime = e.target.currentTime;
                let oldItem = null;
                let item = null;
                for(let i=this.LyricesArr.length-1;i>=0;i--){
                    const v =  this.LyricesArr[i];
                    if (currentTime >= v.startTime) {
                        item = v;
                        break;
                    }else {
                        oldItem = v;
                    }
                }
                if (item === this.currentItem) return;
                this.animate?.cancel();
                if (item) {
                    console.log(currentTime,item.startTime);
                    this.startAnimate(item, oldItem, currentTime)
                }
            }
            // 切割时间
            getStartTime(time) {
                let second = 0;
                const times = time.split(":")
                // 分钟
                second += Number.parseFloat(times[0] * 60)
                // 秒
                second += Number.parseFloat(times[1]);
                // 毫秒
                return second.toFixed(2);
            }
            // 未完成 (废弃)
            sendSearch(keyword) {
                fetch(`http://10.7.44.129:8889/music/search?csrf_token=hlpretag=&hlposttag=&s=${keyword}&type=1&offset=0&total=true&limit=10`, {
                    method: "get",
                    credentials: 'include',
                    headers: {
                    },
                }).then(res => res.json()).then(res => {
                    for (let i = 0; i < res.result.songs.length; i++) {
                        this.musicDOM.innerHTML += `<span>${res.result.songs[i]}</span>`
                    }
                })
            }
            // 重新设置audio音乐地址
            getMusic() {
                // fetch(`http://localhost:8889/music/m/${this.musicId}`, {
                //     method: "get"
                // }).then(res => res.blob()).then(res => {
                //     console.log(res);
                // })
                this.audio.src = `https://music.163.com/song/media/outer/url?id=${this.musicId}.mp3`
            }
            // 获取歌词
            getLyrics() {
                this.LyricesArr = [];
                this.musicDOM.innerHTML = "";
                //34367845
                fetch(`http://10.7.44.129:8889/music/${this.musicId}`, {
                    method: "get"
                }).then(res => res.json()).then(res => {
                    const Lyrics = res.lyric.split("\n").filter(item => item.length > 0);
                    for (let i = 0; i < Lyrics.length; i++) {
                        const lines = Lyrics[i].split("]");
                        
                        if (lines[1].length <= 0) {
                            console.log(lines[0]);
                            continue};
                        const span = document.createElement("span");
                        span.innerHTML = `${lines[1]}`
                        this.musicDOM.appendChild(span);
                        this.LyricesArr.push({
                            startTime: this.getStartTime(lines[0].substring(1)),
                            dom: span,
                            index: this.LyricesArr.length
                        }); 
                    }
                })
            }
            // 歌词滚动动画
            startAnimate(item, oldItem, currentTime) {
                this.musicDOM.style.top = `calc(50% - ${30 * item.index}px)`;
                this.currentItem = item;
                console.log(item.dom);
                this.animate = item.dom.animate([
                    { backgroundPositionX: "-100%" },
                    { backgroundPositionX: "-200%" },
                ], {
                    iterations: 1,
                    duration: (oldItem.startTime -( item?.startTime??0)) * 1000,
                    easing: "linear",
                })
                this.animate.currentTime = (currentTime -item?.startTime??0) * 1000
                if (this.status === "pause") {
                    this.animate?.pause();
                }
                function animationend() {
                    item.dom.removeEventListener("animationend", animationend)
                }
                item.dom.addEventListener("animationend", animationend)
            }
        }


        const music = new Music(".music__wrapper", "#audio");
        music.getMusic()
        music.getLyrics()


    </script>
</body>

</html>

拿到网易云的路由地址

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值