简易音乐播放器(适配pc和移动端)

120 阅读1分钟

废话不多说直接上代码

  1. html部分
   <div class="audio-wrapper"  style="background-color: #fcfcfc;max-width: 670px;height: 90px;border: 1px solid #e0e0e0;">
        <audio class="audio" src="https://oss.igandan.com/audio/mp3/2023/08/20/1692528842680.mp3" >
        </audio>
        <div class="audio-left" style="float: left;text-align: center;width: 22%;height: 100%;">
            <img src="https://tmanager.igandan.org/testUeditor/ueditor/themes/default/images/play.png" class="playicon" style="width: 40px;position: relative;top: 25px;margin: 0;display: initial;cursor: pointer;"/>
            <!-- <img src="/testUeditor/ueditor/themes/default/images/play.png" class="pauseicon" style="width: 40px;position: relative;top: 25px;margin: 0;display: none;cursor: pointer;"/> -->
        </div>
        <div class="audio-right" style="margin-right: 5%;float: right;width: 73%;height: 100%;">
            <p class="audio-title" style="max-width: 490px; font-size: 15px; height: 35%; margin: 8px 0px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;">
                红尘客栈
            </p>
            <div class="progress-bar-bg progressBarBg" style="background-color: #d9d9d9;position: relative;height: 2px;cursor: pointer;">
                <span class="progressDot" style="width: 12px;height: 12px;border-radius: 50%;-moz-border-radius: 50%;-webkit-border-radius: 50%;background-color: #3e87e8;position: absolute;left: 0;top: -5px;margin-left: 0px;cursor: pointer;"></span>
                <div class="progressBar" style="background-color: #649fec;width: 0;height: 2px;"></div>
            </div>
            <div class="audio-time" style="overflow: hidden;margin-top: -1px;">
                <span class="audioCurTime" style="float: left;margin-top:10px;font-size: 12px;color: #969696">00:00</span><span class="audioTotalTime" style="float: right;margin-top:10px;font-size: 12px;color: #969696">02:53</span>
            </div>
        </div>
    </div>      
  1. js部分代码
<script   src="//lib.baomitu.com/jquery/3.6.0/jquery.js"></script>
<script>
    //设置音乐名字
     $('.audio-title')[0].innerHTML=decodeURI(getQueryVariable("audioName"))//$(window.frameElement).attr("audioName");
      //设置音乐链接
     $(".audio").attr("src",decodeURI(getQueryVariable("audioSrc")))
     document.addEventListener('DOMContentLoaded', function () {
    // 设置音频文件名显示宽度
    var element = document.querySelector('.audio-right');
    var maxWidth = window.getComputedStyle(element, null).width;
    document.querySelector('.audio-right p').style.maxWidth = maxWidth;

    // 可能会有多个音频,逐个初始化音频控制事件
    var audios = document.getElementsByTagName('audio');
    for (var i = 0; i < audios.length; i++) {
        initAudioEvent(i);
    }


}, false);
function getQueryVariable(variable){
    var query = window.location.search.substring(1);
    var vars = query.split("&");
    for (var i=0;i<vars.length;i++) {
        var pair = vars[i].split("=");
        if(pair[0] == variable){return pair[1];}
    }
    return(false);
}

/**
 * 初始化音频控制事件
 * @param {number} index 索引,表示第几个音频(从0开始)
 */
function initAudioEvent(index) {
    var audio = document.getElementsByTagName('audio')[index];
    var audioPlayer = document.querySelectorAll(".playicon")[index];//document.getElementById('audioPlayer' + index);
    audio.addEventListener("canplay", function(){//监听audio是否加载完毕,如果加载完毕,则读取audio播放时间
        document.querySelectorAll(".audioTotalTime")[index].innerText = transTime(audio.duration);
 });

    // 监听音频播放时间并更新进度条
    audio.addEventListener('timeupdate', function () {
        updateProgress(audio, index);
    }, false);

    // 监听播放完成事件
    audio.addEventListener('ended', function () {
        audioEnded(index);
    }, false);

    // 点击播放/暂停图片时,控制音乐的播放与暂停
    audioPlayer.addEventListener('click', function () {
        // 改变播放/暂停图片
        if (audio.paused) {
            //document.querySelectorAll(".playicon").src = 'http://tmanager.igandan.org/testUeditor/ueditor/themes/default/images/pause.png'
            // 暂停其他正在播放的音频
            // var audios = document.getElementsByTagName('audio');
            // for (var i = 0; i < audios.length; i++) {
            //     if (i != index && !audios[i].paused) {
            //         audios[i].pause();
            //         document.querySelectorAll(".playicon")[i].src = '/testUeditor/ueditor/themes/default/images/play.png';
            //     }
            // }
            // 开始播放当前点击的音频
            audio.play();
            document.querySelectorAll(".playicon")[0].src = 'http://tmanager.igandan.org/testUeditor/ueditor/themes/default/images/play.png';
        } else {
            audio.pause();
            document.querySelectorAll(".playicon")[0].src = '/testUeditor/ueditor/themes/default/images/play.png';
        }
    }, false);

    // 点击进度条跳到指定点播放
    // PS:此处不要用click,否则下面的拖动进度点事件有可能在此处触发,此时e.offsetX的值非常小,会导致进度条弹回开始处(简直不能忍!!)
    var progressBarBg = document.querySelectorAll(".progressBar")[index];
    progressBarBg.addEventListener('mousedown', function (event) {
        // 只有音乐开始播放后才可以调节,已经播放过但暂停了的也可以
        if (!audio.paused || audio.currentTime != 0) {
            var pgsWidth = parseFloat(window.getComputedStyle(progressBarBg, null).width.replace('px', ''));
            var rate = event.offsetX / pgsWidth;
            audio.currentTime = audio.duration * rate;
            updateProgress(audio, index);
        }
    }, false);

    // 拖动进度点调节进度
    dragProgressDotEvent(audio, index);
}

/**
 * 鼠标拖动进度点时可以调节进度
 * @param {*} audio
 * @param {number} index 索引,表示第几个音频(从0开始)
 */
function dragProgressDotEvent(audio, index) {
    var dot =document.querySelectorAll(".progressDot")[index];

    var position = {
        oriOffestLeft: 0, // 移动开始时进度条的点距离进度条的偏移值
        oriX: 0, // 移动开始时的x坐标
        maxLeft: 0, // 向左最大可拖动距离
        maxRight: 0 // 向右最大可拖动距离
    };
    var flag = false; // 标记是否拖动开始

    // 鼠标按下时
    dot.addEventListener('mousedown', down, false);
    dot.addEventListener('touchstart', down, false);

    // 开始拖动
    document.addEventListener('mousemove', move, false);
    document.addEventListener('touchmove', move, false);

    // 拖动结束
    document.addEventListener('mouseup', end, false);
    document.addEventListener('touchend', end, false);

    function down(event) {
        if (!audio.paused || audio.currentTime != 0) { // 只有音乐开始播放后才可以调节,已经播放过但暂停了的也可以
            flag = true;

            position.oriOffestLeft = dot.offsetLeft;
            position.oriX = event.touches ? event.touches[0].clientX : event.clientX; // 要同时适配mousedown和touchstart事件
            position.maxLeft = position.oriOffestLeft; // 向左最大可拖动距离
            position.maxRight =document.querySelectorAll(".progressBarBg")[index].offsetWidth - position.oriOffestLeft; // 向右最大可拖动距离
           //document.getElementById('progressBarBg' + index)document
            // 禁止默认事件(避免鼠标拖拽进度点的时候选中文字)
            if (event && event.preventDefault) {
                event.preventDefault();
            } else {
                event.returnValue = false;
            }

            // 禁止事件冒泡
            if (event && event.stopPropagation) {
                event.stopPropagation();
            } else {
                window.event.cancelBubble = true;
            }
        }
    }

    function move(event) {
        if (flag) {
            var clientX = event.touches ? event.touches[0].clientX : event.clientX; // 要同时适配mousemove和touchmove事件
            var length = clientX - position.oriX;
            if (length > position.maxRight) {
                length = position.maxRight;
            } else if (length < -position.maxLeft) {
                length = -position.maxLeft;
            }
            var progressBarBg =document.querySelectorAll(".progressBarBg")[index];// document.getElementById('progressBarBg' + index);
            var pgsWidth = parseFloat(window.getComputedStyle(progressBarBg, null).width.replace('px', ''));
            var rate = (position.oriOffestLeft + length) / pgsWidth;
            audio.currentTime = audio.duration * rate;
            updateProgress(audio, index);
        }
    }

    function end() {
        flag = false;
    }
}

/**
 * 更新进度条与当前播放时间
 * @param {object} audio - audio对象
 * @param {number} index 索引,表示第几个音频(从0开始)
 */
function updateProgress(audio, index) {
    var value = audio.currentTime / audio.duration;
    if(value==1){
        audio.currentTime=0;
        audio.pause();
        document.querySelectorAll(".playicon")[0].src = '/testUeditor/ueditor/themes/default/images/play.png';
    }
    //document.getElementById('progressBar' + index)
    document.querySelectorAll(".progressBar")[index].style.width = value * 100 + '%';
    //document.getElementById('progressDot' + index)
    document.querySelectorAll(".progressDot")[index].style.left = value * 100 + '%';
    //document.getElementById('audioCurTime' + index)
    document.querySelectorAll(".audioCurTime")[index].innerText = transTime(audio.currentTime);
   
}

/**
 * 播放完成时把进度调回开始的位置
 * @param {number} index 索引,表示第几个音频(从0开始)
 */
function audioEnded(index) {
    document.getElementById('progressBar' + index).style.width = 0;
    document.getElementById('progressDot' + index).style.left = 0;
    document.getElementById('audioCurTime' + index).innerText = transTime(0);
    document.getElementById('audioPlayer' + index).src = './image/play.png';

    // 自动播放下一个音频
    var audios = document.getElementsByTagName('audio');
    var nextIndex = (index + 1) >= audios.length ? 0 : index + 1;
    audios[nextIndex].play();
    document.getElementById('audioPlayer' + nextIndex).src = '/testUeditor/ueditor/themes/default/images/pause.png';
}

/**
 * 音频播放时间换算
 * @param {number} value - 音频当前播放时间,单位秒
 */
function transTime(value) {
    var time = "";
    var h = parseInt(value / 3600);
    value %= 3600;
    var m = parseInt(value / 60);
    var s = parseInt(value % 60);
    if (h > 0) {
        time = formatTime(h + ":" + m + ":" + s);
    } else {
        time = formatTime(m + ":" + s);
    }

    return time;
}

/**
 * 格式化时间显示,补零对齐
 * eg:2:4  -->  02:04
 * @param {string} value - 形如 h:m:s 的字符串 
 */
function formatTime(value) {
    var time = "";
    var s = value.split(':');
    var i = 0;
    for (; i < s.length - 1; i++) {
        time += s[i].length == 1 ? ("0" + s[i]) : s[i];
        time += ":";
    }
    time += s[i].length == 1 ? ("0" + s[i]) : s[i];

    return time;
}
</script>
  1. css代码
      .audio-wrapper {
    background-color: #fcfcfc;
    margin: 0px auto;
    max-width: 670px;
    height: 70px;
    border-radius: 8px;
    border: 1px solid #e0e0e0;
    box-shadow: 0 0 5px #ccc;
}

.audio-left {
    float: left;
    text-align: center;
    width: 18%;
    height: 100%;
}

.audio-left img {
    width: 40px;
    position: relative;
    top: 15px;
    margin: 0;
    border-radius: 50%;;
    display: initial;   /* 解除与app的样式冲突 */
    cursor: pointer;
    -webkit-tap-highlight-color:transparent;
}

.audio-right {
    margin-right: 2%;
    float: right;
    width: 80%;
    height: 100%;
}

.audio-right p {
    font-size: 15px;
    height: 35%;
    margin: 8px 0;

    /* 歌曲名称只显示在一行,超出部分显示为省略号 */
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    max-width: 243px;   /* 要适配小屏幕手机,所以最大宽度先设小一点,后面js根据屏幕大小重新设置 */    
}

.progress-bar-bg {
    background-color: #d9d9d9;
    position: relative;
    height: 2px;
    cursor: pointer;
}

.progress-bar {
    background-color: #649fec;
    width: 0;
    height: 2px;
}

.progress-bar-bg span {
    content: " ";
    width: 10px;
    height: 10px;
    border-radius: 50%;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
    background-color: #3e87e8;
    position: absolute;
    left: 0;
    top: 50%;
    margin-top: -5px;
    margin-left: -5px;
    cursor: pointer;
}

.audio-time {
    overflow: hidden;
    margin-top: -1px;
}

.audio-length-total {
    float: right;
    font-size: 12px;
}

.audio-length-current {
    float: left;
    font-size: 12px;
}
.progressDot{
    top: -1px !important;
}