JavaScript(JS) 音乐播放器

代码块中有注释 可以阅读一下 图片和音乐路径不同所以需要自己找一个合适的

播放模式支持:列表播放(默认)、循环播放、随机播放

能控制音量大小、上一曲、下一曲、暂停、播放、播放节奏状态、查看播放列表、删除某条单曲等……功能

顺便封装了个Message的消息提示 状态有(SuccessErrorWarninginfo)

源码下载链接: Javascript模拟音乐播放器-Javascript文档类资源-CSDN下载 

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Music</title>
    <style>
        * {
            box-sizing: border-box;
        }

        .music_image {
            width: 55px;
            height: 55px;
        }

        .music_content {
            display: flex;
            justify-content: space-between;

        }

        .music_title {
            color: #333;
            font-size: 14px;
            font-weight: 600;
        }

        .music_duration {
            font-size: 13px;
            color: #999;
        }

        .music_button {
            display: flex;
            align-items: center;
            margin: 0px 20px;
        }

        .duration_control {
            width: 700px;
        }

        .music_vessel {
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 10px 120px;
            position: fixed;
            left: 0;
            bottom: 0;
            width: 100%;
        }

        .music_up,
        .music_play,
        .music_pause,
        .music_next {
            margin: 0 8px;
            background-size: 100% 100%;
            width: 35px;
            height: 35px;
            cursor: pointer;
        }

        .music_up:hover,
        .music_play:hover,
        .music_pause:hover,
        .music_next:hover {
            opacity: .3;
        }

        .music_up {
            background-image: url("./icon/up.png");
        }

        .music_play {
            background-image: url("./icon/play.png");
        }

        .music_pause {
            background-image: url("./icon/pause.png");
            display: none;
        }

        .music_next {
            background-image: url("./icon/next.png");
        }

        .music_audio {
            display: none;
        }

        #range {
            cursor: pointer;
        }

        .music_mode {
            display: flex;
            width: 100px;
            justify-content: space-between;
            margin: 0 20px;
            position: relative;
        }

        .music_lists {
            position: absolute;
            right: 0;
            width: 400px;
            height: 0px;
            bottom: 35px;
            border-radius: 8px;
            background-color: rgb(243, 243, 243);
            z-index: 2;
            display: none;
            transition: all .3s;
            overflow-y: scroll;
            overflow-x: hidden;
            padding: 10px;
        }

        /* .music_lists>div {
            width: 100%;
            height: 500px;
            border: 1px solid #000;
        } */

        .music_lists>.lists {
            width: 100%;
            max-height: 300px;
            min-height: 300px;
        }

        .music_lists>.info {
            cursor: pointer;
            padding: 10px;
            margin-bottom: 5px;
            display: flex;
            justify-content: space-between;
            font-size: 13px;
            align-items: center;
            border-radius: 5px;
        }

        .music_lists>.info:hover {
            background-color: #fff;
        }

        .music_lists>.active {
            font-weight: 600;
            color: #149ce6;
            background-color: #fff;

        }


        .music_lists>.info>.music_list_index {
            margin-right: 10px;
        }

        .music_lists>.info>.music_list_title {
            width: 90%;
        }

        .music_lists>.info>.music_list_delete {
            width: 18px;
            height: 18px;
            background: url("icon/delete.png") no-repeat;
            background-size: 100% 100%;
        }

        .music_lists>.info>.music_list_delete:hover {
            opacity: 0.5;
        }


        .music_lists::-webkit-scrollbar {
            width: 10px;
        }

        .music_lists::-webkit-scrollbar-thumb {
            /*滚动条里面小方块*/
            border-radius: 5px;
            background: #b8b7b7;
        }

        .music_lists::-webkit-scrollbar-track {
            /*滚动条里面轨道*/
            border-radius: 10px;
            background: transparent;
        }

        .volume_control {
            position: absolute;
            right: 17px;
            bottom: 95px;
            transform: rotate(-90deg);
            background-color: rgb(243, 243, 243);
            border-radius: 8px;
            padding: 0 5px;
            z-index: 1;
            display: none;
        }

        .volume_range {
            cursor: pointer;
        }

        .play_mode,
        .music_list,
        .volume {
            width: 25px;
            height: 25px;
            background-size: 100% 100%;
            cursor: pointer;
            /* border:1px solid #000; */
        }

        .playing {
            display: flex;
            align-items: flex-end;
            height: 10px;
        }

        .playing .side1,
        .playing .side2,
        .playing .side3 {
            width: 2px;
            background-color: #149ce6;
            margin-left: 2px;
        }

        .playing .side1 {
            height: 6px;
            animation: playingSide1 1.2s linear infinite;
        }

        .playing .side2 {
            height: 4px;
            animation: playingSide2 1.2s linear infinite;

        }

        .playing .side3 {
            height: 10px;
            animation: playingSide3 1.2s linear infinite;

        }


        .play_mode {
            background-image: url("icon/cycle.png");
        }

        .volume {
            background-image: url("icon/volume.png");
        }

        .music_list {

            background-image: url("icon/list.png");
            background-size: 90% 90%;
            background-repeat: no-repeat;
            background-position: center bottom;
        }

        @keyframes musicListShow {
            0% {
                height: 0px;
                display: none;
                overflow-y: hidden;
            }

            100% {
                height: 300px;
                display: block;
                overflow-y: hidden;
            }
        }

        @keyframes musicListHidden {
            0% {
                height: 300px;
                display: block;
            }

            100% {
                height: 0px;
                display: none;
            }
        }


        @keyframes playingSide1 {
            0% {
                height: 6px;
            }

            56% {
                height: 10px;
            }

            100% {
                height: 8px;
            }
        }

        @keyframes playingSide2 {
            0% {
                height: 4px;
            }

            28% {
                height: 6px;
            }

            80% {
                height: 12px;
            }

            100% {
                height: 6px;
            }
        }

        @keyframes playingSide3 {
            0% {
                height: 10px;
            }

            56% {
                height: 8px;
            }

            100% {
                height: 6px;
            }
        }


        html,
        body {
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
    </style>
</head>

<body>


    <div class="music_vessel">
        <!-- 默认音乐图片填充 -->
        <img src="./icon/music.png" class="music_image">
        <!-- 操作按钮 -->
        <div class="music_button">
            <!-- 上一首 -->
            <div class="music_up"></div>
            <!-- 播放 -->
            <div class="music_play"></div>
            <!-- 暂停 -->
            <div class="music_pause"></div>
            <!-- 下一首 -->
            <div class="music_next"></div>

        </div>
        <div class="music_info">
            <!-- 显示时长 -->
            <div class="music_content">
                <span class="music_title">
                    你好世界,欢迎收听你的月亮我的心!
                </span>
                <span class="music_duration">
                    0:00 / 0:00
                </span>
            </div>
            <!-- 时长控制 -->
            <input type="range" id="range" class="duration_control" value="0" disabled>


        </div>
        <div class="music_mode">
            <!-- 音量 -->
            <div class="volume"></div>
            <div class="volume_control">
                <input type="range" class="volume_range" value="100" max="100">
            </div>
            <!-- 播放模式 -->
            <div class="play_mode"></div>
            <!-- 播放列表 -->
            <div class="music_list"></div>
            <div class="music_lists">

            </div>
        </div>
    </div>
    <audio src="" class="music_audio"></audio>

</body>
<script>


    // 获取DOM元素
    const $ = Dom => document.querySelector(Dom);
    const class$ = Dom => document.querySelectorAll(Dom);
    const volumeBtn = $(".volume"); //音量按钮
    const musicListBtn = $(".music_list"); //列表按钮
    const musicListsBox = $(".music_lists");//列表显示容器
    const musicAudio = $(".music_audio"); //重中之重 音乐控件
    const musicTitle = $(".music_title"); //音乐标题 
    const musicUp = $(".music_up"); // 上一首
    const musicDuration = $(".music_duration"); // 时长显示
    const durationControl = $(".duration_control"); //时长控制
    const musicPlay = $(".music_play") // 播放
    const musicPause = $(".music_pause")// 暂停
    const musicNext = $(".music_next") // 下一首
    let activePlay = -1; // 当前播放的那一首
    let playModeStatus = "cycle"; //播放模式 (默认)cycle:列表循环 oneCycle:单曲循环 random:随机播放
    const playModeStatusObj = {
        cycle: "oneCycle",
        oneCycle: "random",
        random: "cycle",
    }
    const musicList = [
        { title: "万能青年旅店 - sha死那个石家庄人", url: "./audio/万能青年旅店 - sha死那个石家庄人.mp3" },
        { title: "隔壁老樊 - 姬和不如", url: "./audio/隔壁老樊 - 姬和不如.flac" },
        { title: "宋冬野 - 安和桥", url: "./audio/宋冬野 - 安和桥.flac" },
        { title: "宋冬野 - 董小姐", url: "./audio/宋冬野 - 董小姐.flac" },
        { title: "Ayo97  周思涵 - 感谢你曾来过", url: "./audio/Ayo97  周思涵 - 感谢你曾来过.mp3" },
        { title: "队长 - 哪里都是你", url: "./audio/队长 - 哪里都是你.flac" },
        { title: "C.HØPE - 沉沦与遐想", url: "./audio/C.HØPE - 沉沦与遐想.mp3" },
        { title: "Copy,BT07 - 晚风", url: "./audio/Copy,BT07 - 晚风.mp3" },
        { title: "Round_2 - Kill The Game", url: "./audio/Round_2 - Kill The Game.mp3" },
        // { title: "艾福杰尼 - Yellow Skin Flow", url: "./audio/艾福杰尼 - Yellow Skin Flow.ape" },
        { title: "烟把儿乐队 - 纸短情长", url: "./audio/烟把儿乐队 - 纸短情长.mp3" },
        { title: "周杰伦 - 以父之名", url: "./audio/周杰伦 - 以父之名.flac" },

    ] //音乐播放列表

    // 消息提醒
    const message = (messageInfo) => {
        let messageStatus = {
            success: {
                color: "#67C23A",
                backgroundColor: "#F0F9EB"
            },
            warning: {
                color: "#E6A23C",
                backgroundColor: "#FDF6EC"
            },
            error: {
                color: "#F56C6C",
                backgroundColor: "#FEF0F0"
            },
        }
        let messageDom = document.createElement("div");
        let keepTime = messageInfo.keepTime || 1500
        messageDom.innerText = messageInfo.message || ""
        let messageStyle = {
            color: "#909399",
            backgroundColor: "#EDF2FC",
            position: "fixed",
            top: "-20%",
            left: "50%",
            transform: "translate(-50% , 0)",
            width: "420px",
            borderRadius: "5px",
            boxSizing: "border-box",
            padding: "15px 20px",
            transition: "all 0.6s",
        };

        if (messageInfo.type) {
            messageStyle.color = messageStatus[messageInfo.type].color;
            messageStyle.backgroundColor = messageStatus[messageInfo.type].backgroundColor;
        }

        for (let styleKey in messageStyle) {
            messageDom.style[styleKey] = messageStyle[styleKey];
        }

        document.body.appendChild(messageDom)
        setTimeout(() => {
            messageDom.style['top'] = "10%";
        })

        setTimeout(() => {
            messageDom.style['top'] = "-20%"
            setTimeout(() => {
                messageDom.remove()
            }, 600)

        }, keepTime)
    }

    // 渲染播放列表
    const createMusicList = () => {
        let musicListHtml = "";
        // <div class="music_list_index">${index + 1}< /div>
        musicList.forEach((el, index) => {
            musicListHtml += `
                <div class="info ${activePlay == index ? 'active' : ''}" data-index="${index}"> 
                    <div class="music_list_index">
                        ${activePlay == index ?
                    `<div class="playing">
                        <div class="side1"></div>
                        <div class="side2"></div>
                        <div class="side3"></div>
                     </div>`
                    : index + 1}
                    </div>
                    
                    <div class="music_list_title">${el.title}</div>
                    <div class="music_list_delete" data-index="${index}"></div>
                </div>`
        })

        musicListsBox.innerHTML = musicListHtml;
        // 点击播放
        class$(".info").forEach((dom_el) => {
            dom_el.onclick = (e) => {
                activePlay = dom_el.dataset['index'];
                initialize();
            }
        })
        // 
        class$(".music_list_delete").forEach((dom_el) => {
            dom_el.onclick = (e) => {
                e.stopPropagation();
                musicList.splice(dom_el.dataset['index'], 1);
                if (activePlay == dom_el.dataset['index']) {
                    activePlay--;
                    initialize();
                }
                createMusicList()

            }
        })
    }

    // 播放模式控制
    $(".play_mode").onclick = (e) => {
        playModeStatus = playModeStatusObj[playModeStatus];
        $(".play_mode").style.backgroundImage = `url("icon/${playModeStatus}.png")`;
    }

    // 音量按钮
    volumeBtn.onclick = (e) => {
        $(".volume_control").style.display == "block" ? $(".volume_control").style.display = "none" : $(".volume_control").style.display = "block";
    }

    // 控制音量
    $(".volume_control").children[0].onchange = (e) => {
        musicAudio.volume = $(".volume_control").children[0].value / 100
    }


    // 列表点击事件
    musicListBtn.onclick = (e) => {
        musicListsBox.style.animation == "musicListShow .3s linear" ? musicListsBox.style.animation = "musicListHidden .3s linear" : musicListsBox.style.animation = "musicListShow .3s linear"
        setTimeout(() => {
            musicListsBox.style.display == 'block' ? (musicListsBox.style.display = "none") : (musicListsBox.style.display = "block")
        }, 300)
        musicListsBox.style.height == '300px' ? (musicListsBox.style.height = "0px") : (musicListsBox.style.height = "300px")
        createMusicList()
    }
    //播放模式 (默认)cycle:列表循环 oneCycle:单曲循环 random:随机播放
    // 上一首
    musicUp.onclick = (e) => {
        if (activePlay === 0 && playModeStatus != "random") {
            message({ type: "warning", message: "已经是第一首了" })
            return;
        }
        if (activePlay !== -1 && playModeStatus != "random") {
            activePlay--;
        }
        if (playModeStatus == 'random') {
            activePlay = Math.floor(Math.random() * 11);
        }

        initialize();

    }
    // 下一首
    musicNext.onclick = (e) => {
        if (musicList.length == 0) {
            message({ type: "error", message: "播放列表中暂无歌曲" });
            return;
        }
        if (activePlay == musicList.length - 1 && playModeStatus != "random") {
            activePlay = 0;
            initialize();
            return;
        }

        if (activePlay !== -1 && playModeStatus != "random") {
            activePlay++;
        }

        if (playModeStatus == 'random') {
            activePlay = Math.floor(Math.random() * 11);
        }

        initialize();
    }

    // 渲染音频
    const initialize = () => {
        if (musicList.length == 0) {
            message({ type: "error", message: "播放列表中暂无歌曲" });
            musicTitle.innerText = "你好世界,欢迎收听你的月亮我的心!";
            musicAudio.src = "";
            durationControl.disabled = true;
            durationControl.value = 0;
            return;
        }


        if (activePlay === -1) {
            activePlay = 0;
        }

        createMusicList()
        musicTitle.innerText = musicList[activePlay].title;
        musicAudio.src = musicList[activePlay].url;
        durationControl.disabled = false;
        musicAudio.play();

    }


    // 时长控制器状态值发生改变时
    durationControl.onchange = (e) => {
        musicAudio.currentTime = durationControl.value;
    }

    // 歌曲开始播放时
    musicAudio.onplay = (e) => {
        musicPlay.style.display = "none";
        musicPause.style.display = "block";
        [...$(".playing").children].forEach(el => el.style.animationPlayState = "")

    }

    // 歌曲暂停时
    musicAudio.onpause = (e) => {
        musicPlay.style.display = "block";
        musicPause.style.display = "none";
        [...$(".playing").children].forEach(el => el.style.animationPlayState = "paused")
    }


    // 歌曲播放结束时
    musicAudio.onended = (e) => {
        musicPlay.style.display = "block";
        musicPause.style.display = "none";
        if (playModeStatus == "oneCycle") {
            musicAudio.play()
            return;
        }
        if (activePlay == musicList.length - 1 && playModeStatus == "cycle") {
            activePlay = 0;
            initialize();
            return;
        }
        if (activePlay != musicList.length - 1 && playModeStatus != "oneCycle") {
            activePlay++;
        }

        if (playModeStatus == 'random') {
            activePlay = Math.floor(Math.random() * 11);
        }
        initialize();
    }
    // 时长更改时会执行
    musicAudio.ontimeupdate = (e) => {
        if (musicAudio.currentTime >= 0 && musicAudio.duration >= 0) {
            let totalF = parseInt(musicAudio.duration / 60); //总时长 分钟
            let totalM = parseInt(musicAudio.duration % 60); //总时长 秒数
            let currentF = parseInt(musicAudio.currentTime / 60);
            let currentM = parseInt(musicAudio.currentTime % 60) < 10 ? '0' + parseInt(musicAudio.currentTime % 60) : parseInt(musicAudio.currentTime % 60);
            musicDuration.innerHTML = ` ${currentF}:${currentM} / ${totalF}:${totalM}`;
            durationControl.max = musicAudio.duration;
            durationControl.value = musicAudio.currentTime;
        }
    }

    // 开始播放
    musicPlay.onclick = (e) => {
        if (activePlay !== -1) {
            musicAudio.play();
            return;
        }
        initialize()
    }

    musicPause.onclick = (e) => {
        musicAudio.pause();
    }


</script>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值