温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

JS怎么实现进度条顺滑功能

发布时间:2021-08-02 10:22:23 来源:亿速云 阅读:138 作者:chen 栏目:开发技术

本篇内容主要讲解“JS怎么实现进度条顺滑功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JS怎么实现进度条顺滑功能”吧!

进度条不顺滑

相信大多前端同学都自己写过音频、视频播放器,实现并不复杂。最近在小程序里,做了一个类似微博刷视频的需求。其中有一部分功能需要实现自定义进度条,在做完第一版之后发现进度条不顺滑,而后想查查网上看有没有什么好的方案,但最终没找到合适的。于是想看看微信小程序里的“微博”进度条如何,结果也是很生硬的动画,下面放了一个GIF,大家也可以自己搜索微信小程序的微博,找个视频看看效果。

JS怎么实现进度条顺滑功能

常规方案

最终决定还是优化一下这个问题,先来捋一捋我们现有常规方案。

  • 监听TimeUpdate事件

  • 获取到当前播放时间,通过总时间计算进度百分比(currentTime / duration * 100)

  • 进度条width属性设置进度百分比

现有的方案是依赖事件获取当前播放时间,而这个事件大概在100~350毫秒触发一次,下面是我记录的小程序的事件对象队列。

[
    {"detail":{"currentTime":0.10509,"duration":5.83}},
    {"detail":{"currentTime":0.364527,"duration":5.83}},
    {"detail":{"currentTime":0.613648,"duration":5.83}},
]

目前的问题在于,每次获取到事件,就会更新进度条,没有过度动画效果,非常的生硬,下面是一个5s总时长的进度条变化过程:

JS怎么实现进度条顺滑功能

核心代码:

const onProgress = (e, $dom) => {
    const updateFunc = (percent) => {
        $dom.style.width = percent+'%'
    }
    let percent = ((e.detail.currentTime / e.detail.duration) * 100).toFixed(1)
    updateFunc(percent)
}

transition

我们能很快想到用CSS的动画属性来做优化,想要灵活的控制,我选择使用 transition。transition可以定义动画执行时长,当我们改变width时,transition就会在规定时间内用动画的方式改变进度条宽度。首先动画执行时长一定要固定,并且在上一个执行时长结束之前最好不要再对width做改动,否则会导致冲突,动画会变得很奇怪。

  • 选择一个合理的transition执行时间:0.5s

  • 根据当前总时长,求出0.5s在进度条中所属百分比(100/duration/2)

  • 第一次TimeUpdate事件,就执行width改变,把进度条设置到0.5s的位置:width = 100/duration/2

  • 非第一次TimeUpdate事件,每当currentTime超过上一次进度条位置,就更新当前进度条百分比

听起来有点不好理解,我们画个图:

JS怎么实现进度条顺滑功能

  1. 当第一次触发TimeUpdate事件,0.1336秒的时候(当然这个值随机的,可能是0.1~0.3之间),我们就设置width到0.5s的位置,这样进度条就和视频同步在运动,和真实的进度相差微弱的0.1秒。在动画执行的0.5s之间,UpdateTime也会有多次触发,

  2. 当某次UpdateTime的currentTime(0.7123s,这个值也是随机的)值大于上次执行的0.5s时,这个时候进度条的位置大概也在0.5s周围,我们再次触发下一个0.5s动画,也就是把width设置为1s的进度条位置

  3. 而后下个迭代currentTime>1s,width设置为1.5s,这样循环下去。

核心代码:

const playControl = {
  percent: 0,
  time: 0,
  duration: 0,
  first: true
}
const onProgress = (e, $dom) => {
    const updateFunc = (percent) => {
        playControl.percent = percent
        playControl.time = e.detail.currentTime
        $dom.style.width = percent+'%'
    }
    //当前视频进度第一次更新
    if (playControl.first) {
        playControl.duration = e.detail.duration
        playControl.first = false
        updateFunc(100 / e.detail.duration / 2)
    } else {
        let percent = ((e.detail.currentTime / e.detail.duration) * 100).toFixed(1)
        if (percent - playControl.percent > 0 || e.detail.currentTime >= e.detail.duration) {
            updateFunc(percent)
        }
    }
}

最终效果对比(PS:gif图效果有折损)

JS怎么实现进度条顺滑功能

60s版本看起来和普通版差不多?把另一个60s挡住,来回对比,会发现还是有些区别。

解释起来还是有点费劲,还是没看明白?直接去看github仓库代码,代码可直接运行:https://github.com/zimv/smooth-progress

此方案在部分场景下会有短暂延迟,比如暂停、拖动等,个人总体觉得利大于弊。

到此,相信大家对“JS怎么实现进度条顺滑功能”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

js
AI