You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

纯HTML/CSS/JS音乐播放器:Next按钮切换时播放图标切换异常求助

音乐播放器Next/Previous按钮切换时的播放图标同步问题

我用纯HTML、CSS和JS开发了一款音乐播放器,用来巩固JS知识,参考YouTube项目实现了基础功能并加入自己的想法。现在遇到的问题是:点击底部Next/Previous按钮切换歌曲时,希望歌曲列表中当前播放歌曲的按钮显示暂停图标(fa-circle-pause),上一首的按钮恢复为播放图标(fa-circle-play),尝试多种方法没成功。

网站代码

HTML

<body>
    <nav>
        <ul class="flex">
            <li class="logo"><i class="fa-brands fa-napster fa-2xl">Nolae-fy</i></li>
        </ul>
    </nav>

    <div class="container ">
        <div class="songList"></div>
        <h1 class="heading">Enjoy the essence of Hallyu (한류) </h1>
        <div>
            <div class="songItem flex">
                <img  alt="">
                <span class="songName">Meaningful Stone - A Call from My Dream</span>
                <span class="songlistplay"><span class="timestamp">4:19 <i id="0" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
            <div class="songItem flex">
                <img  alt="">
                <span class="songName">Paul Blanco - 믿어(Believe) (Feat. Crush)</span>
                <span class="songlistplay"><span class="timestamp">3:07 <i id="1" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
            <div class="songItem flex">
                <img alt="">
                <span class="songName">Meaningful Stone - A Call from My Dream</span>
                <span class="songlistplay"><span class="timestamp">4:19 <i id="2" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
            <div class="songItem flex">
                <img alt="">
                <span class="songName">Meaningful Stone - A Call from My Dream</span>
                <span class="songlistplay"><span class="timestamp">4:19 <i id="3" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
            <div class="songItem flex">
                <img alt="">
                <span class="songName">Meaningful Stone - A Call from My Dream</span>
                <span class="songlistplay"><span class="timestamp">4:19 <i id="4" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
            <div class="songItem flex">
                <img alt="">
                <span class="songName">Meaningful Stone - A Call from My Dream</span>
                <span class="songlistplay"><span class="timestamp">4:19 <i id="5" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
            <div class="songItem flex">
                <img alt="">
                <span class="songName">Meaningful Stone - A Call from My Dream</span>
                <span class="songlistplay"><span class="timestamp">4:19 <i id="6" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
            <div class="songItem flex">
                <img alt="">
                <span class="songName">Meaningful Stone - A Call from My Dream</span>
                <span class="songlistplay"><span class="timestamp">4:19 <i id="7" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
            <div class="songItem flex">
                <img alt="">
                <span class="songName">Meaningful Stone - A Call from My Dream</span>
                <span class="songlistplay"><span class="timestamp">4:19 <i id="8" class="fa-solid songItemPlay  fa-circle-play padding"></i></span>
            </div>
        </div>
        <div class="songBanner"></div>
    </div>

    <div class="bottom flex">
        <input type="range" name="range" id="myProgressBar" value="0" min="0" max="100">
        <div class="icons">
            <i class="fa-solid fa-2x fa-backward-step" id="previous"></i>
            <i id="masterPlay" class="fa-solid fa-2x fa-circle-play"></i>
            <i class="fa-solid fa-2x fa-forward-step" id="next"></i>
        </div>
        <div class="songInfo">
            <img src="/img/sakura.gif" alt="" id="gif"><span id="masterSongName">Meaningful Stone - A Call from My Dream</span>
        </div>
    </div>
   
    <script src="script.js"></script>
  
</body>

JS

console.log("Welcome to Nolae-fy!")
let songIndex = 0
let audioElement = new Audio('song/1.mp3');
let masterPlay = document.getElementById("masterPlay");
let myProgressBar = document.getElementById("myProgressBar");
let gif = document.getElementById("gif");
let songItems = Array.from(document.getElementsByClassName('songItem'));
let miniPlay= Array.from(document.getElementsByClassName('songItemPlay'));

let masterSongName = document.getElementById("masterSongName");

let songs = [
    {songName:"Meaningful Stone - A Call from My Dream", filePath:"song/dream.mp3",coverPath:"cover/dream.jpeg"},
    {songName:"Paul Blanco - 믿어(Believe) (Feat. Crush)", filePath:"song/believe.mp3",coverPath:"cover/believe.jpeg"},
    {songName:"Lexie Liu- 佳人 (Kappa Girl)", filePath:"song/kappa.mp3",coverPath:"cover/kappa.jpeg"},
    {songName:"Jay Park - Need to Know", filePath:"song/needtoknow.mp3",coverPath:"cover/needtoknow.jpeg"},
    {songName:"Jungkook - My Time", filePath:"song/mytime.mp3",coverPath:"cover/mytime.jpeg"},
    {songName:"KAI (EXO) - 음 (Mmmh)", filePath:"song/mmmh.mp3",coverPath:"cover/mmmh.jpeg"},
    {songName:"HIGH4 IU- Not Spring, Love, or ..", filePath:"song/spring.mp3",coverPath:"cover/spring.jpeg"},
    {songName:"EXO 엑소 - 'Ko Ko Bop'", filePath:"song/kokobop.mp3",coverPath:"cover/kokobop.jpeg"},
    {songName:"BIBI(비비)- KAZINO", filePath:"song/kazino.mp3",coverPath:"cover/kazino.jpeg"},
]

songItems.forEach((element,i)=>{
    element.getElementsByTagName("img")[0].src = songs[i].coverPath;
    element.getElementsByClassName("songName")[0].innerText = songs[i].songName;
})

masterPlay.addEventListener("click",()=>{
    if(audioElement.paused || audioElement.currentTime<=0){
        audioElement.play()
        masterPlay.classList.remove('fa-circle-play')
        masterPlay.classList.add('fa-circle-pause')
        gif.style.opacity = 1;
    } else{
        audioElement.pause()
        masterPlay.classList.remove('fa-circle-pause')
        masterPlay.classList.add('fa-circle-play')
        gif.style.opacity = 0;
    }
})

audioElement.addEventListener('timeupdate',()=>{
    progress = parseInt((audioElement.currentTime/audioElement.duration)*100)
    myProgressBar.value = progress
})

myProgressBar.addEventListener("change",()=>{
    audioElement.currentTime = myProgressBar.value * audioElement.duration/100
})

const makeAllPlays = ()=>{
    Array.from(document.getElementsByClassName('songItemPlay')).forEach((element)=>{
        element.classList.remove('fa-circle-pause')
        element.classList.add('fa-circle-play')
    })
}

Array.from(document.getElementsByClassName("songItemPlay")).forEach((element)=>{
    element.addEventListener('click',(e)=>{
        makeAllPlays();
        songIndex = parseInt(e.target.id);
        e.target.classList.remove('fa-circle-play');
        e.target.classList.add('fa-circle-pause');
        audioElement.src = `song/${songIndex+1}.mp3`;
        masterSongName.innerText = songs[songIndex].songName;
        audioElement.currentTime = 0 ; 
        audioElement.play();
        masterPlay.classList.remove('fa-circle-play')
        masterPlay.classList.add('fa-circle-pause')
        gif.style.opacity = 1;
    })
})

const makeNewPlays = ()=>{
    Array.from(document.getElementsByClassName('songItemPlay')).forEach((element)=>{
        element.classList.remove('fa-circle-pause')
        element.classList.add('fa-circle-play')
     }

document.getElementById('next').addEventListener('click',()=>{
    if(songIndex>=8){
        songIndex = 0 
    } else{
        songIndex += 1
    }
    makeNewPlays();
    audioElement.src = `song/${songIndex+1}.mp3`;
    masterSongName.innerText = songs[songIndex].songName;
    audioElement.currentTime = 0 ; 
    audioElement.play();
    masterPlay.classList.remove('fa-circle-play')
    masterPlay.classList.add('fa-circle-pause')
    gif.style.opacity = 1;
})

document.getElementById('previous').addEventListener('click',()=>{
    if(songIndex<=0){
        songIndex = 0 
    } else{
        songIndex -= 1
    }
    makeNewPlays();
    audioElement.src = `song/${songIndex+1}.mp3`;
    masterSongName.innerText = songs[songIndex].songName;
    audioElement.currentTime = 0 ; 
    audioElement.play();
    masterPlay.classList.remove('fa-circle-play')
    masterPlay.classList.add('fa-circle-pause')
    gif.style.opacity = 1;
})

网站截图

音乐播放器截图


问题修复方案

问题分析

你的代码存在两个核心问题:

  1. makeNewPlays函数语法不完整,缺少闭合的}),导致函数无法执行
  2. 切换歌曲后,没有主动将当前歌曲对应的列表按钮切换为暂停图标

具体修复步骤

  1. 修正makeNewPlays函数语法
    直接复用已有的makeAllPlays函数(功能完全一致),删除冗余的makeNewPlays,或者修正其语法:

    const makeNewPlays = ()=>{
        Array.from(document.getElementsByClassName('songItemPlay')).forEach((element)=>{
            element.classList.remove('fa-circle-pause')
            element.classList.add('fa-circle-play')
        })
    }
    
  2. 添加当前歌曲图标切换逻辑
    在Next和Previous按钮的点击事件中,调用makeAllPlays()重置所有图标后,给当前songIndex对应的按钮设置暂停图标:

Next按钮修改后代码

document.getElementById('next').addEventListener('click',()=>{
    if(songIndex>=8){
        songIndex = 0 
    } else{
        songIndex += 1
    }
    makeAllPlays();
    // 设置当前歌曲按钮为暂停图标
    const currentBtn = document.getElementById(songIndex);
    currentBtn.classList.remove('fa-circle-play');
    currentBtn.classList.add('fa-circle-pause');
    
    audioElement.src = `song/${songIndex+1}.mp3`;
    masterSongName.innerText = songs[songIndex].songName;
    audioElement.currentTime = 0 ; 
    audioElement.play();
    masterPlay.classList.remove('fa-circle-play')
    masterPlay.classList.add('fa-circle-pause')
    gif.style.opacity = 1;
})

Previous按钮修改后代码

document.getElementById('previous').addEventListener('click',()=>{
    if(songIndex<=0){
        songIndex = 0 
    } else{
        songIndex -= 1
    }
    makeAllPlays();
    // 设置当前歌曲按钮为暂停图标
    const currentBtn = document.getElementById(songIndex);
    currentBtn.classList.remove('fa-circle-play');
    currentBtn.classList.add('fa-circle-pause');
    
    audioElement.src = `song/${songIndex+1}.mp3`;
    masterSongName.innerText = songs[songIndex].songName;
    audioElement.currentTime = 0 ; 
    audioElement.play();
    masterPlay.classList.remove('fa-circle-play')
    masterPlay.classList.add('fa-circle-pause')
    gif.style.opacity = 1;
})

额外优化

可以把图标切换逻辑封装成单独函数,减少重复代码:

const updatePlayIcons = (currentIndex) => {
    makeAllPlays();
    const btn = document.getElementById(currentIndex);
    btn.classList.remove('fa-circle-play');
    btn.classList.add('fa-circle-pause');
}

之后在需要切换图标的地方直接调用updatePlayIcons(songIndex)即可。

内容的提问来源于stack exchange,提问作者Antarik Chetia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 12:37:04