前端提高篇(六十五):HTML5练习1:个性音乐播放器(二)

本文详细介绍了如何使用HTML和JavaScript创建一个简单的音乐播放器。包括音频文件的加载、播放控制、进度显示及拖拽等功能的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.引入audio文件,放在main里的img后;刷新之后,起始时间是:00:00,总时长在oncanplay里通过duration获取

<main class="main">
    <img src="./source/1.jpg" alt="">
    <audio id='audio' src="./source/song.mp3"></audio>
</main>
var oAudio = document.getElementById('audio'),
    ocurrentTime = document.getElementsByClassName('current-time')[0],
    oallTime = document.getElementsByClassName('all-time')[0];

oAudio.oncanplay = function() {
    oallTime.innerHTML = coverTime(this.duration);
    ocurrentTime.innerHTML = '00:00';
}
//调整时间为xx:xx格式
function coverTime(t){
    var sec = parseInt(t % 60) < 10 ? '0'+parseInt(t % 60) : parseInt(t % 60);
    var min = parseInt(t / 60) < 10 ? '0'+parseInt(t / 60) : parseInt(t / 60);
    return min + ':' + sec;

}

在这里插入图片描述
2.面板左边的暂停播放效果

var	oBtn = document.getElementsByClassName('btn')[0],
    oIsPlay = oBtn.getElementsByClassName('iconfont')[0];
    
oBtn.onmouseup = function(){
    if (oAudio.paused) {
        oAudio.play();
        oIsPlay.className = 'iconfont icon-zanting_huaban';
    }
    else {
        oAudio.pause();
        oIsPlay.className = 'iconfont icon-bofang';
    }
}

图标名称以iconfont给的html里标注的为准

3.面板中间的进度条随时间前移
在计时器中需要使用总时长来计算当前进度条的width,不必要每次计时器工作都要获取一次duration,所以在oncanplay时,获取一次,并赋值给全局变量即可
刷新的时候pro-activate宽度为0,radio在进度条的最左边,
之前我把radio设置在.radio-box的右边,把.radio-box设置在白色条右边,当白色条宽度为0时,.radio-box会在pro-box最左边,且没有和pro-box重合,所以应该把radio-box往右移8px(radio的直径),进度条行走的路程应该是pro-box的宽-8px;
在这里插入图片描述

在这里插入图片描述

.radio-box {
    width: 20px;
    height: 20px;
    position: absolute;
    right: -8px;
    top: -9px;
    background: rgba(0,255,0,0.2);
}
var timer,
    duration,
    bgWid = oBg.offsetWidth - 8;/*圆点走的最长长度*/
oBtn.onmouseup = function(){
    if (oAudio.paused) {
        oAudio.play();
        oIsPlay.className = 'iconfont icon-zanting_huaban';
        timer = setInterval(movePro, 1000);
    }
    else {
        oAudio.pause();
        oIsPlay.className = 'iconfont icon-bofang';
        clearInterval(timer);
    }
}
function movePro() {
    var currentTime = oAudio.currentTime;
    var w = currentTime / duration * bgWid;/*当前播放时间/总时长=当前宽度/总路径长度*/
    ocurrentTime.innerHTML = coverTime(currentTime);
    // console.log(currentTime,duration,w);
    oproActivate.style.width = w  + 'px';
}

刷新时:
在这里插入图片描述
音频播放结束时:
在这里插入图片描述

这里有一个问题,当点击暂停,然后又开始播放时,时间可能会对不上,从7s直接到9s,中间的8被跳过了,没显示出来,
图中第一个参数是当前时间,第二个是总时长,最后一个是计算的当前宽度,
而且,时间并不是1s的整数,说明计数器并不是特别准确,
在这里插入图片描述
所以我们可以把采样时间缩小一些,获取的间隔短一些,就不会错过时间了

4.设置循环播放,当播放到最后时,暂停,当前时间改为0,activate宽度改成0,重新开始播放
为了提高代码的复用性,把之前写的暂停和播放的代码封装成musicPlay和musicPause函数

oAudio.onended = function(){
    musicPause();
    oAudio.currentTime = 0;
    oproActivate.style.width = 0;
    musicPlay();
}

5.设置拖拽,鼠标按下,并拖拽进度条,调整到自己想要的地方放手,左边的时长对应变化,歌也相应调到那个地方继续播放
5.1我们对包裹圆点的盒子设置mousedown事件
当鼠标往下按时,此时的进度条不再跟着计数器往前走(计数器每200ms执行一次,询问当前播放时间,设置左侧时间和当前进度条长度),而是由鼠标移动来决定进度条的位置
所以我们在鼠标点下之后,清空了计数器

5.2我们对整个body设置鼠标移动事件mousemove,不仅在进度条部分才能响应鼠标的移动,但这个移动事件,在鼠标按下进度条上圆点附近之后才触发,否则鼠标随意移动,进度条就跟着鼠标移动起来

5.3 getBoundingClientRect()可以获得该元素相对浏览器左右上下的距离,返回的是一个对象,通过.left来获取距离浏览器左侧的值
更多关于getBoundingClientRect()的知识
鼠标将进度条拖拽到一个位置,此时鼠标相对于浏览器的横坐标是可以知道的
我们将鼠标横坐标与圆点起点位置(pro-box最左边部分)相减,就能知道进度条应该拖到哪里
在这里插入图片描述
值得注意的是,音乐实际播放时,进度条前进的路程不是这段,

如果设上面图示的距离为newWidth,讲道理,实际走的时长应该是:(newWidth-4) / bgWid * duration;
(当前播放时长/总时长 = 进度条前进的距离/总长度,总长度是bgWid = pro-box的长度-8)
在这里插入图片描述
然后我设置之后的结果是,我用鼠标拖到一个位置,进度条自己又弹回去了
在这里插入图片描述
这个弹回去的动作,感觉像是因为手形的那个位置从radio-box中心转到radio中心,手型不动,所以box就回退了
我可能要考虑radio-box中心和radio中心不一致的影响
我的radio设置在radio-box的右侧,radio直径8px,radio-box宽20px,所以radi-box中心点离radio最左边边缘2px,我改了公式为:
(newWidth+2) / bgWid * duration
就不弹了
但是这个路径该怎么解释呢

后来发现,其实这个减多少,跟前一个算width的有关系,在第三点的最后一行代码oproActivate.style.width = w + 'px';有关系,如果这里加了4,变成oproActivate.style.width = w + 4 + 'px';,这里c = (newWidth - 4) / bgWid * duration;就不会弹了
但是这样会让第一步前进跨的步子太大
在这里插入图片描述

所以,我决定,直接用圆点的半径去堵这4px就好了,不需要自己额外计算,纠结了这么久,终于结束

oradioBox.onmousedown = function(){
    clearInterval(timer);
    var c = oAudio.currentTime;
    document.body.onmousemove = function(e){
        var newWidth = e.clientX - oproBox.getBoundingClientRect().left;
        if (newWidth < 8){
            newWidth = 8;
        }else if (newWidth > 160){
            newWidth = 160;
        }
        oproActivate.style.width = newWidth + 'px';
        c = newWidth / bgWid * duration;
       
        ocurrentTime.innerHTML = coverTime(c);
    }
    document.body.onmouseup = function(){
        document.body.onmousemove = null;
        document.body.onmouseup = null;
        musicPlay();
        oAudio.currentTime = c;
    }
}

在用mouseup时,由于之前在btn上也用过mouseup,需要清空,否则在执行前面的mouseup时,由于冒泡,会让这个mouseup也执行

效果:
在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值