内嵌音乐播放器

14 篇文章 0 订阅
5 篇文章 0 订阅

讲解一个基本的播放器,包含基本的功能实现。

播放器制作的成品。代码直接在后面拿,注意歌曲对象的格式。 

1.分析基本结构

我们可以发现这个界面的基本结构可以分为两个部分,一个部分是歌曲的top 一个部分是歌曲的bottom

这边直接使用flex布局进行,划分,上二下一 对上面的内容继续进行划分。使用flex布局完成之后的划分

页面布局

页面的基本布局代码

我直接放到后面的完整代码里面了,这样我好写文字。

基本布局结束之后,我们这时候需要书写一下播放的基本逻辑,这个文本编辑器字数一高直接就卡的受不了。

播放逻辑

我们需要保证,当播放到对应的音乐时,歌词和歌曲背景,歌曲名称,播放的链接都需要进行更改,那么现在我们需要先获取到这些页面元素,获取之后,我们直接进行讲相同功能的模块进行封装,封装之后直接拿给对应逻辑的监听调用即可。

1.播放和暂停

        注意切换界面的显示和当前播放的音乐对象的内容

2.上一曲和下一曲

        注意播放到第一首和最后一首的播放情况

        注意当歌曲没有播放的时候,点击下一首或者上一首的时候,保证歌曲的顺利播放

3.自动播放

        设置一个函数来监听歌曲的完成,当歌曲完成时,自动切换到下一曲。

4.设置记录上一次

        我们直接使用本地储存的知识点来进行上一次内容的记录,直接记录下来播放的索引即可。

5.播放进度条的显示

        根据歌曲的播放进度进行进度条的显示内容

注意这部分内容的切换就行。我感觉可能没人会看这个内容。

1/28日更新:

增加随鼠标拖动移动以及右键菜单功能

完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        .box {
            padding: 10px;
            display: flex;
            flex-direction: column;
            position: fixed;
            right: 10px;
            bottom: 10px;
            width: 200px;
            height: 200px;
            background-repeat: no-repeat;
            background-size: cover;
        }

        .box::after {
            top: 0;
            left: 0;
            backdrop-filter: blur(5px);
            position: absolute;
            width: 200px;
            height: 200px;
            background-color: rgba(0, 0, 0, .4);
            content: "";
            z-index: -10;
        }

        .box::before:hover {
            color: yellow;
        }

        .box .top-music {
            display: flex;
            flex: 2;
            flex-direction: column;
            background-color: transparent;
        }

        .box .bottom-music-ci {
            position: relative;
            display: flex;
            color: crimson;
            justify-content: center;
            align-items: center;
            flex: 1;
            overflow: hidden;
        }

        .box .bottom-music-ci::before {
            width: 100%;
            height: 100%;
            content: "";
            position: absolute;
            z-index: 999;
        }

        .box .top-music .top-music-name {
            background-color: transparent;
            display: flex;
            flex: 1;
            justify-content: center;
            align-items: center;
            color: orange;
            position: relative;
        }

        .box .top-music .top-music-name::before {
            width: 100%;
            height: 100%;
            content: "";
            position: absolute;
            z-index: 999;
        }

        .name-font {
            font-size: 14px;
        }

        .box .top-music .top-music-load {
            padding-top: 10px;
            display: flex;
            flex: 1;
            justify-content: center;
            align-items: center;
        }

        .box .top-music .top-music-use {
            display: flex;
            flex: 1;
            flex-direction: row;
            justify-content: center;
            align-items: center;
        }

        .box .top-music .top-music-use .font-music {
            display: flex;
            flex: 1;
            flex-direction: row;
            justify-content: center;
            align-items: center;
            cursor: pointer;
        }

        .box .top-music .top-music-use .paused-music {
            display: flex;
            flex: 1;
            flex-direction: row;
            justify-content: center;
            align-items: center;
            cursor: pointer;
        }

        .box .top-music .top-music-use .next-music {
            display: flex;
            flex: 1;
            flex-direction: row;
            justify-content: center;
            align-items: center;
            cursor: pointer;
        }

        #progressBar {
            width: 200px;
            height: 10px;
        }

        .hidden {
            display: none;
        }

        .content {
            display: flex;
            justify-content: center;
            align-items: center;
            width: 100%;
            height: 100%;
            padding: 5px;
            overflow: hidden;
        }

        .menu {
            font-size: 14px;
            width: 50px;
            position: absolute;
            background-color: black;
            color:white;
            display: none;
            z-index:9999 ;

        }

        .menu-item {
            cursor: pointer;
        }
        .hidden {
            display: none;
        }
        .hidden-menu {
            display: none;
        }
    </style>
</head>
<body>
<div class="box">
    <div class="top-music">
        <div class="top-music-name">
            <span class="name-font">歌曲-[歌手]</span>
        </div>
        <div class="top-music-load">
            <audio id="audioPlayer"
                   src="https://m801.music.126.net/20240120222846/c4a039de7557dbc52bf7d266edd82802/jdymusic/obj/wo3DlMOGwrbDjj7DisKw/10563287967/a70c/70ad/0e2b/c921856c6dab06aaa3c663a4932ef7e4.mp3"></audio>
            <progress id="progressBar" value="0" max="100"></progress>
        </div>
        <div class="top-music-use">
            <div class="font-music">
                <svg t="1705760253968" class="icon" viewBox="0 0 1024 1024" version="1.1"
                     xmlns="http://www.w3.org/2000/svg" p-id="7683" width="32" height="32">
                    <path d="M512 62.389956c-248.312412 0-449.610044 201.297632-449.610044 449.610044s201.297632 449.610044 449.610044 449.610044 449.610044-201.297632 449.610044-449.610044S760.312412 62.389956 512 62.389956zM786.507004 786.507004c-35.672454 35.672454-77.196173 63.672158-123.416867 83.222423-47.821145 20.22667-98.655927 30.482245-151.09116 30.482245-52.435233 0-103.270015-10.255575-151.09116-30.482245-46.220694-19.549242-87.744413-47.549969-123.416867-83.222423-35.672454-35.672454-63.672158-77.196173-83.222423-123.416867-20.22667-47.821145-30.482245-98.655927-30.482245-151.090137 0-52.435233 10.255575-103.270015 30.482245-151.09116 19.549242-46.220694 47.549969-87.744413 83.222423-123.416867 35.672454-35.672454 77.196173-63.672158 123.416867-83.222423 47.821145-20.22667 98.654904-30.482245 151.09116-30.482245 52.435233 0 103.268992 10.255575 151.09116 30.482245 46.220694 19.549242 87.744413 47.549969 123.416867 83.222423 35.672454 35.672454 63.672158 77.196173 83.222423 123.416867 20.22667 47.821145 30.482245 98.655927 30.482245 151.09116 0 52.435233-10.255575 103.268992-30.482245 151.090137C850.179163 709.310831 822.179458 750.83455 786.507004 786.507004z"
                          p-id="7684" fill="#e6e6e6"></path>
                    <path d="M715.830315 305.667701 448.346261 507.980453c-3.094478 1.786693-3.094478 6.252401 0 8.039093l267.484054 202.312752c3.094478 1.786693 6.961552-0.446162 6.961552-4.019547l0-404.625504C722.791867 306.113863 718.924793 303.881009 715.830315 305.667701z"
                          p-id="7685" fill="#e6e6e6"></path>
                    <path d="M398.078391 306.049395l-92.229564 0c-2.563382 0-4.640694 2.365884-4.640694 5.28333l0 401.334551c0 2.917446 2.078335 5.28333 4.640694 5.28333l92.229564 0c2.563382 0 4.641717-2.365884 4.641717-5.28333L402.720108 311.332724C402.719084 308.415278 400.641773 306.049395 398.078391 306.049395z"
                          p-id="7686" fill="#e6e6e6"></path>
                </svg>
            </div>
            <!--            这个位置设置成点击及播放的效果会更好一点-->
            <div class="paused-music">
                <svg t="1705760359255" class="icon hidden" id="pause" viewBox="0 0 1024 1024" version="1.1"
                     xmlns="http://www.w3.org/2000/svg" p-id="8784" width="32" height="32">
                    <path d="M512 128a382.6 382.6 0 1 1-149.45 30.15A381.54 381.54 0 0 1 512 128m0-64C264.58 64 64 264.58 64 512s200.58 448 448 448 448-200.58 448-448S759.42 64 512 64z"
                          p-id="8785" fill="#e6e6e6"></path>
                    <path d="M384 320v384-384m0-64a64 64 0 0 0-64 64v384a64 64 0 0 0 64 64 64 64 0 0 0 64-64V320a64 64 0 0 0-64-64zM640 320v384-384m0-64a64 64 0 0 0-64 64v384a64 64 0 0 0 64 64 64 64 0 0 0 64-64V320a64 64 0 0 0-64-64z"
                          p-id="8786" fill="#e6e6e6"></path>
                </svg>
                <svg t="1705760529073" class="icon" id="open" viewBox="0 0 1024 1024" version="1.1"
                     xmlns="http://www.w3.org/2000/svg" p-id="11757" width="32" height="32">
                    <path d="M924.5 337.9c-22.6-53.3-54.8-101.2-95.9-142.3-41.1-41.1-89-73.4-142.3-95.9C631.1 76.4 572.4 64.5 512 64.5c-60.4 0-119.1 11.8-174.3 35.2-53.3 22.6-101.2 54.8-142.3 95.9s-73.4 89-95.9 142.3c-23.4 55.2-35.2 113.9-35.2 174.3s11.8 119.1 35.2 174.3c22.6 53.3 54.8 101.2 95.9 142.3s89 73.4 142.3 95.9c55.2 23.4 113.9 35.2 174.3 35.2 60.4 0 119.1-11.8 174.3-35.2 53.3-22.6 101.2-54.8 142.3-95.9 41.1-41.1 73.4-89 95.9-142.3 23.4-55.2 35.2-113.9 35.2-174.3s-11.8-119-35.2-174.3z m-146.8 440c-71 71-165.3 110-265.7 110-100.4 0-194.7-39.1-265.7-110-71-71-110-165.3-110-265.7s39.1-194.7 110-265.7 165.3-110 265.7-110c100.4 0 194.7 39.1 265.7 110s110 165.3 110 265.7-39.1 194.7-110 265.7z"
                          p-id="11758" fill="#e6e6e6"></path>
                    <path d="M706.7 464.8L447.6 300.6c-17.3-11-39.2-11.6-57.1-1.8-17.9 9.9-29.1 28.7-29.1 49.2v328c0 20.5 11.1 39.3 29.1 49.2 8.5 4.7 17.8 7 27.1 7 10.4 0 20.9-2.9 30-8.7l259.1-163.8c16.4-10.3 26.1-28.1 26.2-47.5-0.1-19.3-9.9-37.1-26.2-47.4zM433.4 647.3V376.8L647 512.2 433.4 647.3z"
                          p-id="11759" fill="#e6e6e6"></path>
                </svg>
            </div>
            <div class="next-music">
                <svg t="1705760207636" class="icon" viewBox="0 0 1024 1024" version="1.1"
                     xmlns="http://www.w3.org/2000/svg" p-id="6527" width="32" height="32">
                    <path d="M512 62.389956c-248.312412 0-449.610044 201.297632-449.610044 449.610044s201.297632 449.610044 449.610044 449.610044 449.610044-201.297632 449.610044-449.610044S760.312412 62.389956 512 62.389956zM786.507004 786.507004c-35.672454 35.672454-77.196173 63.672158-123.416867 83.222423-47.821145 20.22667-98.655927 30.482245-151.09116 30.482245-52.435233 0-103.270015-10.255575-151.09116-30.482245-46.220694-19.549242-87.744413-47.549969-123.416867-83.222423-35.672454-35.672454-63.672158-77.196173-83.222423-123.416867-20.22667-47.821145-30.482245-98.655927-30.482245-151.090137 0-52.435233 10.255575-103.270015 30.482245-151.09116 19.549242-46.220694 47.549969-87.744413 83.222423-123.416867 35.672454-35.672454 77.196173-63.672158 123.416867-83.222423 47.821145-20.22667 98.654904-30.482245 151.09116-30.482245 52.435233 0 103.268992 10.255575 151.09116 30.482245 46.220694 19.549242 87.744413 47.549969 123.416867 83.222423 35.672454 35.672454 63.672158 77.196173 83.222423 123.416867 20.22667 47.821145 30.482245 98.655927 30.482245 151.09116 0 52.435233-10.255575 103.268992-30.482245 151.090137C850.179163 709.310831 822.179458 750.83455 786.507004 786.507004zM575.653739 507.980453 308.169685 305.667701c-3.094478-1.786693-6.961552 0.446162-6.961552 4.019547l0 404.625504c0 3.572362 3.868097 5.806239 6.961552 4.019547l267.484054-202.312752C578.747193 514.232854 578.747193 509.767146 575.653739 507.980453zM718.151174 306.049395l-92.229564 0c-2.563382 0-4.640694 2.365884-4.640694 5.28333l0 401.334551c0 2.917446 2.078335 5.28333 4.640694 5.28333l92.229564 0c2.563382 0 4.640694-2.365884 4.640694-5.28333L722.791867 311.332724C722.791867 308.415278 720.714556 306.049395 718.151174 306.049395z"
                          fill="#e6e6e6" p-id="6528"></path>
                </svg>
            </div>
        </div>
    </div>
    <div class="bottom-music-ci">
        <div class="content">
            歌词部分
        </div>
    </div>
    <div class="menu" id="myMenu">
        <div class="menu-item" data-action="action1">最小化</div>
        <div class="menu-item" data-action="action2">最大化</div>
    </div>
</div>
<script>


    // 歌曲id
    var music_open_now = 0
    // 歌曲当前状态
    var status = 1
    // 初始化
    if (!localStorage.getItem('music_open_last')) {
        localStorage.setItem('music_open_last', music_open_now)
    }
    music = [
        {
            "name": "晨曦 Praying theme",
            "artist": "万俟清商",
            "url": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=url&id=2065512248",
            "pic": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=pic&id=109951166958324596",
            "lrc": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=lrc&id=2065512248"
        },
        {
            "name": "在海边",
            "artist": "林鹤洋",
            "url": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=url&id=1964372498",
            "pic": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=pic&id=109951167677740645",
            "lrc": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=lrc&id=1964372498"
        },
        {
            "name": "Ꮺ",
            "artist": "周大发",
            "url": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=url&id=1430751658",
            "pic": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=pic&id=109951165804381199",
            "lrc": "https:\/\/api.injahow.cn\/meting\/?server=netease&type=lrc&id=1430751658"
        }
    ]
    // 首次应该没问题 这个代码就是用来防止说 上一次播放的记录 超过此时的内容了 没啥用
    // if (Math.floor(localStorage.getItem('music_open_last'))>=music.length) {
    //     localStorage.setItem('music_open_last', 0)
    // }
    <!--    歌曲整体内容 用于更换背景 我们可以制作的好看一点 背景主要就是模糊-->
    const box = document.querySelector('.box')
    // 控制开关 显示
    const open = document.querySelector('#open')
    const pause = document.querySelector('#pause')
    // 获取歌曲的名字
    const music_name = document.querySelector('.top-music-name .name-font')
    // 音乐播放
    const audio = document.getElementById("audioPlayer");
    // 进度条内容
    const progressBar = document.getElementById("progressBar");
    // 上一曲 下一曲
    const next_music = document.querySelector('.next-music')
    const font_music = document.querySelector('.font-music')

    const music_ci = document.querySelector('.bottom-music-ci .content')

    // <!--新功能右键菜单栏-->
    var menu = document.querySelector('.menu');
    //     鼠标右击
    box.addEventListener('contextmenu', function (e) {
        // 正常使用的时候 右键会进入浏览器的选项这里阻止事件提交
        e.preventDefault();
        menu.style.display = 'block';
        // 弹出菜单的位置
        menu.style.left = e.clientX - box.getBoundingClientRect().left + 'px';
        menu.style.top = e.clientY - box.getBoundingClientRect().top + 'px';
    });
    // 监听菜单项点击事件
    menu.addEventListener('click', function (e) {
        var action = e.target.getAttribute('data-action');
        if (action) {
            if(action === "action1"){
                console.log("最小化")
            }else if(action === "action2"){
                console.log("最大化")
            }
        }
        menu.style.display = 'none';
    });
    document.addEventListener('click',function (){
        menu.style.display = 'none';
    })
    // 音乐加载内容
    //
    function loadLrc(music_open_now) {
        const url = music[music_open_now]['lrc'];
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status === 200) {
                const responseText = xhr.responseText;
                // 这个呈递的是歌词部分 由于大部分是纯音乐 这里就不便显示
                music_ci.innerHTML = "纯音乐,请欣赏";
            }
        };
        xhr.send();
    }

    function load(music_open_now) {
        audio.src = music[music_open_now]['url'];
        music_name.innerHTML = music[music_open_now]['name'] + '-' + music[music_open_now]['artist'];
        box.style.backgroundImage = `url(${music[music_open_now]['pic'].toString()})`;
        loadLrc(music_open_now)
    }

    // 获取上一次播放的记录
    music_open_now = Math.floor(localStorage.getItem('music_open_last'))
    // 加载上一次歌曲的内容
    load(music_open_now)
    // 歌曲监听
    // 这部分内容由于重复较多 我们可以封装称一个函数 但是由于代码量少 这里不采取提取了,如果采取封装,那么我们只需要监听是获取这个点击对象看一下类名进行判断是+还是-即可,较为简单不多赘述
    next_music.addEventListener('click', function () {
        if (music_open_now == music.length - 1) {
            music_open_now = 0
        } else {
            music_open_now += 1
        }
        load(music_open_now)
        if (status == 1) {
            const hidden = document.querySelector('.hidden')
            hidden.classList.remove('hidden')
            open.classList.add('hidden')
            status = 0
        }
        audio.play()
        localStorage.setItem('music_open_last', music_open_now)
    })
    font_music.addEventListener('click', function () {
        console.log(status)
        if (music_open_now == 0) {
            music_open_now = music.length - 1
        } else {
            music_open_now -= 1
        }

        load(music_open_now)
        if (status == 1) {
            const hidden = document.querySelector('.hidden')
            hidden.classList.remove('hidden')
            open.classList.add('hidden')
            status = 0
        }
        audio.play()
        localStorage.setItem('music_open_last', music_open_now)

    })
    // 播放监听
    open.addEventListener('click', function () {
        const hidden = document.querySelector('.hidden')
        hidden.classList.remove('hidden')
        open.classList.add('hidden')
        status = 0
        console.log(status)
        audio.play()
    })
    pause.addEventListener('click', function () {
        const hidden = document.querySelector('.hidden')
        hidden.classList.remove('hidden')
        pause.classList.add('hidden')
        status = 1
        console.log(status)

        audio.pause()
    })
    // // 设置歌曲链接
    // audio.style.src = music['url']
    // music_name.innerHTML = music['name'] + '-' + music['artist']
    // box.style.backgroundImage = `url(${music['pic'].toString()})`;
    // 监听进度条拖动事件
    progressBar.addEventListener('input', function () {
        // 计算当前播放时间
        var currentTime = (progressBar.value / 100) * audio.duration;
        // 检查是否为非有限值
        if (isFinite(currentTime)) {
            // 设置音频的当前播放时间
            audio.currentTime = currentTime;
        }
    });

    // 监听音频的时间更新事件
    audio.addEventListener('timeupdate', function () {
        // 更新进度条的值
        var progress = (audio.currentTime / audio.duration) * 100;
        // 检查是否为非有限值
        if (isFinite(progress)) {
            progressBar.value = progress;
        }
    });
    // 自动播放
    // 监听歌曲播放结束事件
    audio.addEventListener('ended', function () {
        // 自动切换到下一首歌曲
        if (music_open_now == music.length - 1) {
            music_open_now = 0;
        } else {
            music_open_now += 1;
        }
        load(music_open_now);
        audio.play();
        localStorage.setItem('music_open_last', music_open_now);
    });


    // 鼠标拖动效果增加 中间我给文字效果加上了遮盖 避免出现误触现象
    // 状态 鼠标是否落下 落下的话就需要 记录位置
    var isDragging = false;
    var offsetX, offsetY;

    box.addEventListener('mousedown', function (e) {
        isDragging = true;
        var rect = box.getBoundingClientRect();
        offsetX = e.clientX - rect.left;
        offsetY = e.clientY - rect.top;
    })
    ;

    document.addEventListener('mousemove', function (e) {
        // 根据拖动的边进行移动 效果更佳
        if (isDragging) {
            var x = e.pageX - offsetX;
            var y = e.pageY - offsetY;

            if (x > box.offsetLeft + box.offsetWidth / 2) {
                box.style.left = x - box.offsetWidth + 'px';
            } else {
                box.style.left = x + 'px';
            }

            if (y > box.offsetTop + box.offsetHeight / 2) {
                box.style.top = y - box.offsetHeight + 'px';
            } else {
                box.style.top = y + 'px';
            }
        }
    });

    document.addEventListener('mouseup', function () {
        isDragging = false;
    });


</script>
</body>
</html>
  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值