JS實現(xiàn)進度條順滑版詳細方案
進度條不順滑
相信大多前端同學都自己寫過音頻、視頻播放器,實現(xiàn)并不復雜。最近在小程序里,做了一個類似微博刷視頻的需求。其中有一部分功能需要實現(xiàn)自定義進度條,在做完第一版之后發(fā)現(xiàn)進度條不順滑,而后想查查網(wǎng)上看有沒有什么好的方案,但最終沒找到合適的。于是想看看微信小程序里的“微博”進度條如何,結果也是很生硬的動畫,下面放了一個GIF,大家也可以自己搜索微信小程序的微博,找個視頻看看效果。
常規(guī)方案
最終決定還是優(yōu)化一下這個問題,先來捋一捋我們現(xiàn)有常規(guī)方案。
- 監(jiān)聽TimeUpdate事件
- 獲取到當前播放時間,通過總時間計算進度百分比(currentTime / duration * 100)
- 進度條width屬性設置進度百分比
現(xiàn)有的方案是依賴事件獲取當前播放時間,而這個事件大概在100~350毫秒觸發(fā)一次,下面是我記錄的小程序的事件對象隊列。
[ {"detail":{"currentTime":0.10509,"duration":5.83}}, {"detail":{"currentTime":0.364527,"duration":5.83}}, {"detail":{"currentTime":0.613648,"duration":5.83}}, ]
目前的問題在于,每次獲取到事件,就會更新進度條,沒有過度動畫效果,非常的生硬,下面是一個5s總時長的進度條變化過程:
核心代碼:
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的動畫屬性來做優(yōu)化,想要靈活的控制,我選擇使用 transition。transition可以定義動畫執(zhí)行時長,當我們改變width時,transition就會在規(guī)定時間內用動畫的方式改變進度條寬度。首先動畫執(zhí)行時長一定要固定,并且在上一個執(zhí)行時長結束之前最好不要再對width做改動,否則會導致沖突,動畫會變得很奇怪。
- 選擇一個合理的transition執(zhí)行時間:0.5s
- 根據(jù)當前總時長,求出0.5s在進度條中所屬百分比(100/duration/2)
- 第一次TimeUpdate事件,就執(zhí)行width改變,把進度條設置到0.5s的位置:width = 100/duration/2
- 非第一次TimeUpdate事件,每當currentTime超過上一次進度條位置,就更新當前進度條百分比
聽起來有點不好理解,我們畫個圖:
- 當?shù)谝淮斡|發(fā)TimeUpdate事件,0.1336秒的時候(當然這個值隨機的,可能是0.1~0.3之間),我們就設置width到0.5s的位置,這樣進度條就和視頻同步在運動,和真實的進度相差微弱的0.1秒。在動畫執(zhí)行的0.5s之間,UpdateTime也會有多次觸發(fā),
- 當某次UpdateTime的currentTime(0.7123s,這個值也是隨機的)值大于上次執(zhí)行的0.5s時,這個時候進度條的位置大概也在0.5s周圍,我們再次觸發(fā)下一個0.5s動畫,也就是把width設置為1s的進度條位置
- 而后下個迭代currentTime>1s,width設置為1.5s,這樣循環(huán)下去。
核心代碼:
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圖效果有折損)
60s版本看起來和普通版差不多?把另一個60s擋住,來回對比,會發(fā)現(xiàn)還是有些區(qū)別。
解釋起來還是有點費勁,還是沒看明白?直接去看github倉庫代碼,代碼可直接運行:https://github.com/zimv/smooth-progress
此方案在部分場景下會有短暫延遲,比如暫停、拖動等,個人總體覺得利大于弊。
到此這篇關于JS實現(xiàn)進度條順滑版詳細方案的文章就介紹到這了,更多相關JS進度條順滑版 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
淺析Javascript ES6新增值比較函數(shù)Object.is
在Javascript中判斷相等是很常見的,常用的判斷有“==”,“===”,“!=”,“!==”,今天這篇文章我們來學習ES6中的一個方法Object.is(),有需要的可以參考學習。2016-08-08js調試工具 Javascript Debug Toolkit 2.0.0版本發(fā)布
Javascript Debug Toolkit是一個可以跨瀏覽器調試javascript的開源項目,支持在IE,FIREFOX,SAFARI,CHROME等瀏覽器中調試javascript。2.0.0版本做了較大變動,增加以下功能2008-12-12