最近在做音乐播放器页面, 积累了很多有趣的经验, 今天先分享播放进度条的开发过程.
效果
话不多说,先看效果
支持点击修改进度,拖拽修改进度,当然大家肯定都知道ui库里面有现成的,为何要自己造一个
首先著名的ui库中确实都要这样的滑动输入条,比如antd-mobile中的slider
官网:https://mobile.ant.design/zh/components/slider/
效果很多
比我自己造的肯定功能丰富的多,但是亲自试过之后,发现效果不太友好,下面可以看看使用antd-mobile中的slider效果如下:
对比
这是antd-mobile的效果
代码如下:
其实把value属性去掉,这个组件就会丝滑很多,但是音乐播放器,需要随着音频播放,更改进度条,这是必须要的功能,不能去掉。
<div className={
styles.process}>
<div className={
styles.processTime}>
{
currentTime ? formatTime(currentTime) : '00:00'
}
</div>
<Slider
className={
styles.songSlider}
defaultValue={
0}
onAfterChange={
changeProgressValue}
value={
currentTime && duration ? currentTime / duration * 100 : 0}
icon={
<div className={
styles.sliderDot} />}
/>
{
/* <MusicSlider
className={styles.songSlider}
defaultValue={currentTime && duration ? currentTime / duration * 100 : 0}
onAfterChange={change}
value={currentTime && duration ? currentTime / duration * 100 : 0}
/> */}
<div className={
styles.processTime}>
{
duration ? formatTime(duration) : '00:00'
}
</div>
</div>
changeProgressValue事件就是修改音频的currentTime
除此之外,我也试用了其他的依赖库,比如react-slider
https://github.com/zillow/react-slider
但是效果依旧不好,就是因为有这种两三点的滑动,所以导致逻辑复杂,滑动效果就不太丝滑
所以,我就觉得自己造一个,slider组件
点击修改进度
点击事件比较简单,就需要给这个区域绑定点击事件
灰色区域是父元素,红色元素是子元素,红色元素的宽度就是歌曲当前播放进度比分比 * 父元素宽度
首先,需要理清楚几个坐标,如何确定点击这里是音频进度所占比分比
点击当前点的坐标,点击的时候,能够拿到;父元素的宽度,通过getBoundingClientRect().width也能拿到
父元素左边距离最左边的距离,也能拿到getBoundingClientRect().left,也就是下面这段距离。
所以最终的点击函数如下:
// 点击事件
const barClick = (e: React.MouseEvent) => {
// @ts-ignore
const rect = mmProgress.current.getBoundingClientRect()
const activeWidthVal = Math.min(rect.width, Math.max(0, e.clientX - rect.left))
// @ts-ignore
const progress = Math.floor(activeWidthVal / mmProgress.current.clientWidth * 100)
setActiveWidth(progress)
if (onAfterChange) {
onAfterChange(progress)
}
}
拖拽修改进度
在电脑上,需要监听的是鼠标的mouseup和mouseMove事件
在移动端,需要监听的是touchend和touchmove事件
鼠标移动/触屏移动:需要更新进度条的百分比
鼠标弹起/触屏结束:需要更新歌曲的进度
开始事件能够直接绑定在进度小圆点上
开始时,需要获取到开始的坐标,并且存起来,方便移动事件计算