当前位置: 首页 > news >正文

杏坛餐饮网站建站做网站网站建设专业公司

杏坛餐饮网站建站,做网站网站建设专业公司,近期国际热点大事件,玉林做绿化苗木网站的是哪个单位最近在做音乐播放器页面, 积累了很多有趣的经验, 今天先分享播放进度条的开发过程. 效果 话不多说,先看效果 支持点击修改进度,拖拽修改进度,当然大家肯定都知道ui库里面有现成的,为何要自己造一个 首先著名的ui库中确实都要这…

最近在做音乐播放器页面, 积累了很多有趣的经验, 今天先分享播放进度条的开发过程.

效果

话不多说,先看效果

支持点击修改进度,拖拽修改进度,当然大家肯定都知道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><SliderclassName={styles.songSlider}defaultValue={0}onAfterChange={changeProgressValue}value={currentTime && duration ? currentTime / duration * 100 : 0}icon={<div className={styles.sliderDot} />}/>{/* <MusicSliderclassName={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-ignoreconst rect = mmProgress.current.getBoundingClientRect()const activeWidthVal = Math.min(rect.width, Math.max(0, e.clientX - rect.left))// @ts-ignoreconst progress = Math.floor(activeWidthVal / mmProgress.current.clientWidth * 100)setActiveWidth(progress)if (onAfterChange) {onAfterChange(progress)}}

拖拽修改进度

在电脑上,需要监听的是鼠标的mouseup和mouseMove事件

在移动端,需要监听的是touchend和touchmove事件

鼠标移动/触屏移动:需要更新进度条的百分比

鼠标弹起/触屏结束:需要更新歌曲的进度

开始事件能够直接绑定在进度小圆点上

开始时,需要获取到开始的坐标,并且存起来,方便移动事件计算

mouseDown

// 触摸开始事件const barDown = (e: React.TouchEvent) => {startX.current = e.touches[0].pageX// @ts-ignoreleftVal.current = mmProgressInner.current.clientWidthisDrag.current = true}
// 鼠标开始移动const barDown1 = (e: React.MouseEvent) => {startX.current = e.clientX// @ts-ignoreleftVal.current = mmProgressInner.current.clientWidthisDrag.current = true}// tsx
<div className={styles.sliderDot}onMouseDown={barDown1}onTouchStart={barDown}></div>

由于我直接绑定在了tsx元素上,为了防止ts报错,我就写了两个函数,因为两者的类型不同

类型错误如下:

mouseMove

鼠标移动,需要及时更新进度条的样式,也就是红色条的宽度

所以需要计算当前点击的坐标,和上面函数保持的开始移动坐标

然后就是计算百分比,更新样式

// 鼠标/触摸移动事件const barMove = (e: React.TouchEvent & React.MouseEvent) => {if (isDrag.current) {const endX = e.clientX || e.touches[0].pageXconst dist = endX - startX.current// @ts-ignoreconst activeWidthVal = Math.min(mmProgress.current.clientWidth, Math.max(0, leftVal.current + dist))// @ts-ignoreconst progress = Math.floor(activeWidthVal / mmProgress.current.clientWidth * 100)setActiveWidth(progress)dynamicState.current = progress}}

mouseUp

鼠标抬起,这个函数需要说一下,首先需要判断一下是否已经在鼠标抬起时完成了鼠标放下事件mouseDown

为什么呢?防止这两种情况

这两种情况,也会触发mouseMove和mouseUp事件,但是这两种情况都不可以修改进度

所以需要一个变量来判断是否是在小圆点处发生了mouseDown事件

 // 鼠标/触摸释放事件const barUp = () => {// 避免打开Playing组件时触发if (isDrag.current && onAfterChange) {// @ts-ignoreonAfterChange(dynamicState.current)}}

销毁事件

到这里已经接近尾声了,但是注意挂载了事件,需要销毁

useMount(() => {bindEvents()
})useUnmount(()=> {unbindEvents()})// 添加绑定事件const bindEvents = () => {// @ts-ignoremmProgress.current.addEventListener('mousemove', barMove)// @ts-ignoremmProgress.current.addEventListener('mouseup', barUp)// @ts-ignoremmProgress.current.addEventListener('touchmove', barMove)// @ts-ignoremmProgress.current.addEventListener('touchend', barUp)}// 移除绑定事件const unbindEvents = () => {if (mmProgress.current) {// @ts-ignoremmProgress.current.removeEventListener('mousemove', barMove)// @ts-ignoremmProgress.current.removeEventListener('mouseup', barUp)// @ts-ignoremmProgress.current.removeEventListener('touchmove', barMove)// @ts-ignoremmProgress.current.removeEventListener('touchend', barUp)}}

最后全部代码如下:


import classNames from 'classnames'
import { useEffect, useRef, useState } from 'react'
import styles from './index.module.scss'
import { useMount, useUnmount  } from 'ahooks';export default function MusicSlider(props: any) {const { className, defaultValue, onAfterChange, value } = propsconst [activeWidth, setActiveWidth] = useState(defaultValue)const dynamicState = useRef(0)const startX = useRef(0) // 记录最开始点击的x坐标const leftVal = useRef(0) // 记录当前已经移动的距离const isDrag = useRef(false) // 是否可以拖拽const mmProgress = useRef(null)const mmProgressInner = useRef(null)useMount(() => {bindEvents()})useEffect(() => {const progress = Math.floor(value)// @ts-ignoresetActiveWidth(progress)}, [value])useUnmount(()=> {unbindEvents()})// 添加绑定事件const bindEvents = () => {// @ts-ignoremmProgress.current.addEventListener('mousemove', barMove)// @ts-ignoremmProgress.current.addEventListener('mouseup', barUp)// @ts-ignoremmProgress.current.addEventListener('touchmove', barMove)// @ts-ignoremmProgress.current.addEventListener('touchend', barUp)}// 移除绑定事件const unbindEvents = () => {if (mmProgress.current) {// @ts-ignoremmProgress.current.removeEventListener('mousemove', barMove)// @ts-ignoremmProgress.current.removeEventListener('mouseup', barUp)// @ts-ignoremmProgress.current.removeEventListener('touchmove', barMove)// @ts-ignoremmProgress.current.removeEventListener('touchend', barUp)}}// 点击事件const barClick = (e: React.MouseEvent) => {// @ts-ignoreconst rect = mmProgress.current.getBoundingClientRect()const activeWidthVal = Math.min(rect.width, Math.max(0, e.clientX - rect.left))// @ts-ignoreconst progress = Math.floor(activeWidthVal / mmProgress.current.clientWidth * 100)setActiveWidth(progress)if (onAfterChange) {onAfterChange(progress)}}// 触摸开始事件const barDown = (e: React.TouchEvent) => {startX.current = e.touches[0].pageX// @ts-ignoreleftVal.current = mmProgressInner.current.clientWidthisDrag.current = true}
// 鼠标开始移动const barDown1 = (e: React.MouseEvent) => {startX.current = e.clientX// @ts-ignoreleftVal.current = mmProgressInner.current.clientWidthisDrag.current = true}// 鼠标/触摸移动事件const barMove = (e: React.TouchEvent & React.MouseEvent) => {if (isDrag.current) {const endX = e.clientX || e.touches[0].pageXconst dist = endX - startX.current// @ts-ignoreconst activeWidthVal = Math.min(mmProgress.current.clientWidth, Math.max(0, leftVal.current + dist))// @ts-ignoreconst progress = Math.floor(activeWidthVal / mmProgress.current.clientWidth * 100)setActiveWidth(progress)dynamicState.current = progress}}// 鼠标/触摸释放事件const barUp = () => {// 避免打开Playing组件时触发if (isDrag.current && onAfterChange) {// @ts-ignoreonAfterChange(dynamicState.current)}}return (<div className={classNames(className, styles.progress)} ref={mmProgress} onClick={barClick}><div className={styles.bar}></div><div className={styles.outer}></div><div className={styles.inner} ref={mmProgressInner} style={{width: `${activeWidth}%`}}><div className={styles.sliderDot}onMouseDown={barDown1}onTouchStart={barDown}></div></div></div>)
}
http://www.yayakq.cn/news/688704/

相关文章:

  • seo网站托管设计网有哪些
  • 网站开发毕业设计源码推广引流图片
  • 怎么做app和网站购物车主机屋
  • 高端企业网站定制公司做女装网站应怎么定位
  • 网站设计公司那个好著名网页设计师及作品
  • 乐清手机网站世界十大搜索引擎及地址
  • 做物流哪个网站推广好seo站群干什么的
  • 天津关键词优化平台企业网站优化包括哪三个层面
  • 盗号网站怎么做域名分析网站
  • 微网站模板建设的选择丽江北京网站建设
  • 招聘网站的销售怎么做蛋糕电子商务网站建设方案
  • 购买网站做友情链接仁怀那里可以做网站
  • 陕西省高速建设集团公司网站农业建设信息网站
  • 多终端网站开发wordpress框架视频
  • 桥头做网站网站描述代码怎么写
  • 鄂州网站制作企业国外网站设计模板
  • 网站建设公司策划网站建设的基本流程包括哪些
  • wordpress主题仿逛丢甘肃网站seo哪家公司好
  • 深圳做网站便宜网站设计需求原型图
  • 中山骏域网站建设网站建设优化服务新闻
  • 养生网站设计阅读网站建设
  • wordpress注册模板下载地址在运营中seo是什么意思
  • 电子商务网站开发问题研究智邦国际erp系统官网
  • 企业网站建设项目计划书公司自己的网站叫什么
  • 可以做相册的网站公司名称变更说明函
  • 临沂网站推广网订率推广技巧
  • 养殖场网站模板.net响应式网站模板
  • 网页设计与网站建设标准数据网页版浏览器在线使用
  • 网站建设必备条件免费空间网
  • 网站快速有排名wordpress站点被删