【从零到一】用HTML5+CSS+JavaScript实现一个属于自己的mp3免费音乐播放器 (4) JS交互功能(音乐进度条)

🚀 个人主页 极客小俊

✍🏻 作者简介:程序猿、设计师、技术分享

🐋 希望大家多多支持, 我们一起学习和进步!

🏅 欢迎评论 ❤️点赞💬评论 📂收藏 📂加关注

播放进度条功能 🐞
获取进度条信息 🪲

我们在做这个功能的时候,一定要先梳理清楚HTML+CSS结构,你才知道如何去写JS效果

但不管怎么样,作为用户来说,第一时间肯定是点击或者在这个进度条上拖拽,实现快进/快退的效果~

这里我们先做点击事件, 当我们点击进度条,也就相当于点击了最外层的progressContainer元素

然后用一个叫getBoundingClientRect()方法来获取这个元素的信息~

小知识

getBoundingClientRect()方法是DOM方法

用来获取元素在浏览器视口中的位置和尺寸信息 它的返回值是一个DOMRect对象

注意: 视口一般指浏览器的可见区域, 但是不包括地址栏、工具栏这些地方~

我们可以先打印一下看看效果~

代码

javascript 复制代码
//点击进度条某个位置之后计算进度条对应时间点
progressContainer.addEventListener('click', (e) => {
    //获取元素在视口坐标系中的位置和尺寸信息 返回对象
    var rect = progressContainer.getBoundingClientRect();
    console.log(rect);
});

如图

如果你仔细看,你就能看到不管我点击这个progressContainer元素哪里,打印出来的结果都是一样的数据~

如图

仔细展开DOMRect对象, 看一下里面的东西~ 具体如下

属性名 描述
left 元素左边框外侧到视口左侧的距离
right 元素右边框外侧到视口左侧的距离
top 元素上边框外侧到视口顶部的距离
bottom 元素下边框外侧到视口顶部的距离
width 元素的视觉宽度
height 元素的视觉高度
x 等同于 left
y 等同于 top

注意:

这里面的属性,主要我们要留意以下width和height,它们并不是独立存储的,而是通过边界坐标计算~

width: 你其实可以理解为元素的 (右边框外侧到视口左侧的距离 - 左边框外侧到视口左侧的距离)

同理

height: 你其实可以理解为元素的 (下边框外侧到视口顶部的距离 - 上边框外侧到视口顶部的距离)

那么这意味着width和height属性其实是元素实际占据的宽高,同时还包括内容、内边距、边框

计算用户点击进度 音频条跳转到当前播放位置 🍂

那么当我们点击这个外层容器的时候,获取了它本身的数据,我们才能够往下一步进行计算!

首先要计算出用户点击这个进度条上的位置

这里需要借助事件对象中的clientX属性, 它能获取到鼠标在整个浏览器视口中的水平坐标位置~

那么我们可以用这个鼠标水平坐标位置 - 元素左边框外侧到视口左侧的距离

理解:这里我们主要计算的就是,当用户点击进度条某个位置之后, 所要知道进度条对应时间点

如图

所以,我要知道的是当用户点击进度条时,先算出点击位置相对于进度条左侧的水平距离

再用这个距离去除以进度条总宽度得到点击位置占比,最后用该占比去乘以音频总时长得到当前音频播放位置

最后把计算出来的值赋值到音频播放位置,也就是currentTime属性, 让音频跳转到对应时间点即可!

那逻辑我们梳理清楚了,代码自然也就出来了!

代码如下

javascript 复制代码
//点击进度条某个位置之后计算进度条对应时间点
progressContainer.addEventListener('click', (e) => {
    //获取元素在视口坐标系中的位置和尺寸信息 返回对象
    var rect = progressContainer.getBoundingClientRect();
    //计算当前点击的位置
    var clickX = e.clientX - rect.left;
    // 用这个clickX距离除以进度条总宽度得到点击位置占比,
    // 最后用这个占比乘以音乐的总时长,把计算出来的结果赋值到当前音频播放位置
    audio.currentTime = (clickX / rect.width) * audio.duration;//算出当前快进的音乐位置
    console.log(audio.currentTime);
    //同时播放音乐
    audio.play();
});

如图

如果你还不明白,这里我们来举个栗子:

音频总时长就像一整个10寸的蛋糕 , 比如音频总长10秒,蛋糕就10寸,

进度条的总宽度就对应这整个蛋糕的大小

当你点进度条的某个位置,就像在蛋糕上指了想吃的那一口,先算出你指的位置离蛋糕左边沿有几寸, 对应代码里 clickX结果

重点来了,因为我们的进度条是固定的,但是我们的音频的时长不固定,那么要如何计算才能自适应进度条呢?

所以再用这个几寸除以蛋糕总寸数(进度条总宽度),就能算出你要吃的位置占整个蛋糕的比例

比如点在6寸位置,6÷10=0.6,相当于是60%, 最后用这个比例乘以音频总时长 例如: 0.6 × 10秒 =6秒

那么音频就直接跳到6秒的位置播放,就像直接吃到蛋糕 60%的位置~

现在明白了吗?!

实时更新进度条状态 🌚

我们在上面把进度条的位置计算出来之后,还要让滑块动起来呀~

这里我们需要使用到一个叫timeupdate事件 它是属于HTML5 Audio/Video 事件,大家可以去查一下文档

如图

它的作用就是可以实时帮我们追踪目前的播放位置已更改之后,所发生的状态!~

也就是说一旦音频播放的位置发生了变化,那么这个事件就会被触发!

大家可以先想一下,什么情况下,播放位置会发生变化?

是不是当我们使用play()方法开始播放的时候,它的音频位置就是一直变化的~

我们可以先测试一下看看~

javascript 复制代码
audio.addEventListener('timeupdate', () => {
    console.log(audio.currentTime);
});

如图

所以当我们开始播放音乐的时候,这个事件其实就已经默认一直在触发着!

那我们就可以利用这一点来让进度条的滑块动起来了!

计算方式如下:

javascript 复制代码
(当前播放位置秒 / 当前音频的总秒) * 100;

逻辑分析:

音频播放时会不停触发这段代码,先确认音频有总时长~不然就不执行!

音频已播放时间 除以 音频总时长,再乘以100, 这样来算出百分之多少,

最后把进度条的宽度设为这个百分比!

当然我们这个事件函数在执行的时候,是不断执行的,所以这个百分比也会不断变化,

这样可以让我们的progressBar元素动起来,从而达到一种视觉效果~

具体代码

javascript 复制代码
//使用timeupdate时间,实时更新进度条位置状态
//currentTime 设置或返回音频中的当前播放位置(以秒计) 
//duration 返回当前音频的长度(以秒计) 
audio.addEventListener('timeupdate', () => {
    if (!audio.duration) return;
    var progress = (audio.currentTime / audio.duration) * 100;  
    //最后把这个百分比值赋值给中间层
    //然后最内层的滑块样式圆形因为绝对定位与父元素,
    //会被中间层的动态宽度带过来!
    progressBar.style.width = progress+'%';  
});

当然这里可能有人会问,为什么不用像素,要用百分比?

用百分比是因为进度条宽度是相对的, 这样可以适配不同尺寸容器,按播放占比设百分比能精准对应音频播放进度,用像素那就要先算进度条总像素再乘占比,有点麻烦,并且适配性差!

那么做到这一步,我们的播放器也有一个大概的雏形了~

如图


"👍点赞" "✍️评论" "收藏❤️"
大家的支持就是我坚持下去的动力!


如果以上内容有任何错误或者不准确的地方,🤗🤗🤗欢迎在下面 👇👇👇 留个言指出、或者你有更好的想法,
欢迎一起交流学习❤️❤️💛💛💚💚


更多好玩 好用 好看的干货教程可以点击下方 关注❤️微信公众号 ❤️
说不定有意料之外的收获哦..🤗嘿嘿嘿、嘻嘻嘻🤗!
🌽🍓🍎🍍🍉🍇

相关推荐
Frag0ut40 分钟前
【深度思考】前端基石的觉醒:探讨 HTML 语言的再进化方向
html5·前端开发·前端架构·大前端·webcomponents·技术趋势·浏览器api
福兮说41 分钟前
前端下载大文件,点了按钮半天没反应:fetch + blob 的三个问题和三种替代写法
前端·javascript·性能优化·文件下载
今年下半年3 小时前
【VUE】整合腾讯地图、自定义区域边界、村委名称及资产统计(放大显示资产点位)
前端·javascript·vue.js
可乐鸡翅yeah_6 小时前
hls.js 切换多个视频源,新手开发常见踩坑
开发语言·前端·javascript·ios·ffmpeg·音视频·safari
kyriewen6 小时前
我实测了前端日期的 5 个坑:差 8 小时只是开始
前端·javascript·程序员
anew___6 小时前
《从零手写操作系统 (11):文件系统初探——initrd与VFS抽象层》
java·javascript·算法
今年下半年6 小时前
【VUE3】移动端:使用腾讯地图显示区域统计与放大显示资产点位
javascript·前端框架·vue·地图
a努力。7 小时前
LangChain Agent消息链路全解析
java·前端·javascript
今年下半年7 小时前
【前端】ant-design-vue 表格「行、列都动态」的处理方案
前端·javascript·vue.js
默_笙8 小时前
🚕 缺料就出门买:给 RAG 装上"信息够不够"的判断力
前端·javascript