【前端】關(guān)于幀內(nèi)刷新的一點(diǎn)想法。我為什么拋棄框架。
由于最近想歇歇(前一段忙拍攝上云和大版本升級(jí)太累了?。。?,給自己放了個(gè)假,鼓搗前端。
產(chǎn)品給了一句沒頭沒尾的需求:體驗(yàn)要和FinalCut一樣。
然后,我又想讓他看我電腦鎖屏:這個(gè)需求做不了,I don't want to do this shit!
PS:依舊沒碰云剪輯,另外一個(gè)業(yè)務(wù)場(chǎng)景。
然后研究了一下Final的操作為何會(huì)覺得如此絲滑。
今天要講的一個(gè)細(xì)節(jié):
幾乎所有在畫面上調(diào)整,滑塊調(diào)整,都是幀內(nèi)完成,也就是說,鼠標(biāo)操作的跟隨,全部在當(dāng)前幀完成。
別問我咋知道的。錄了操作的錄屏,傳到分秒幀,用逐幀播放功能一幀一幀看過的。(為了給后面維護(hù)的同學(xué)留下證據(jù),原生JS寫代碼,真不是我有那個(gè)大病。)

場(chǎng)景:
不方便說,就反正類似我們現(xiàn)在在視頻上圈點(diǎn)畫標(biāo)注的功能,需要鼠標(biāo)拖動(dòng)時(shí),畫面上實(shí)時(shí)產(chǎn)生變化的場(chǎng)景。
解決方案
由React重構(gòu)為原生JS,外層在套入React。組件內(nèi)部操作不使用數(shù)據(jù)驅(qū)動(dòng)。
整站的技術(shù)棧在使用React,所以其實(shí)很多組件當(dāng)時(shí)寫的時(shí)候也是數(shù)據(jù)驅(qū)動(dòng)。也就是,鼠標(biāo)按下時(shí)改變狀態(tài),然后移動(dòng)時(shí)計(jì)算位置坐標(biāo),直接set到子組件進(jìn)行位置更新的方式。
這個(gè)方式存在的問題就擺在那了。查了一遍之前的代碼。很多setXXX useEffect({},[xxx])的玩意兒。假設(shè)經(jīng)過一次數(shù)據(jù)的監(jiān)聽和計(jì)算之后再Set回去,然后Render的時(shí)候再改。鼠標(biāo)點(diǎn)按和位置改變,就差了一幀。鼠標(biāo)移動(dòng)較慢的情況下一般1-2個(gè)像素,較快的情況下。10幾個(gè)像素也是有可能的。就會(huì)有種不絲滑的感覺了。
div重繪問題也比較顯著。數(shù)據(jù)變了,然后這個(gè)div……就重新生成了一個(gè)。(這點(diǎn)我也十分驚訝)組件套組件之后。div渲消耗?沒幀都產(chǎn)生了新的,GC消耗????……emmm 自己想吧,不多做解釋了。
這個(gè)地方需要加一個(gè)我們自己的場(chǎng)景遇到的問題:
時(shí)間碼
剪輯過視頻的小伙伴可能會(huì)注意到這個(gè)東西。視頻非編工具,大致上是這樣的 時(shí):分:秒:幀 音頻則是 時(shí):分:秒:毫秒。假設(shè)我們把音頻的 一個(gè)數(shù)據(jù)記錄(44100HZ 就是單聲道1秒 44100個(gè)數(shù)據(jù)記錄,實(shí)際上毫秒都不足以計(jì)明白)anyway無論音頻還是視頻。在我們公司產(chǎn)品里,確實(shí)要求時(shí)間碼需要和視頻的幀數(shù)強(qiáng)一致。
但往往,視頻播放組件,和時(shí)間戳顯示組件,就根本不是同一個(gè)組件。需要數(shù)據(jù)Prop。好吧。。這次場(chǎng)景。。都不在一個(gè)項(xiàng)目里(講真)。主站引用不同的兩個(gè)包。。。
這時(shí)候,你監(jiān)聽數(shù)據(jù)變化。很抱歉,不是差一幀就是差兩幀。極度惡心。音頻更顯著。畢竟毫秒是計(jì)量單位。
而且。。。video標(biāo)簽和Audio標(biāo)簽的ontimeupdate一秒只觸發(fā)四次。播放過程中,每一幀和他的時(shí)間碼對(duì)上,這事兒。。就挺惡心的。當(dāng)然,好在這些差異,其實(shí)只在播放中體現(xiàn)。暫停之后。顯示器刷新一兩幀之后。也就自然而然的對(duì)上了?;旧现挥辛薋CP和PR的人才會(huì)覺得好像有哪別扭。
處理這個(gè)問題必然是根本不set 需要用到的組件需要能直接調(diào)用到video/audio標(biāo)簽的currentTime,RAF刷新innerText。(雖然不難,但就是覺得在React項(xiàng)目里,寫這玩意,是很有那個(gè)大?。?/p>
時(shí)不時(shí)打開性能簽,調(diào)試單幀內(nèi)調(diào)用棧所用時(shí)長。
調(diào)試技巧吧算是。首先,我開發(fā)用的顯示屏刷新率實(shí)際在 60HZ。之前發(fā)現(xiàn)過這個(gè)問題。感覺開發(fā)時(shí)候很順暢的東西,拿到120HZ顯示屏測(cè)。效果就跟屎一樣。
這個(gè)時(shí)候,首先確保寫的前端組件自身能不能支持到120HZ的刷新頻率。也就是8.33毫秒內(nèi)完成所有計(jì)算和渲染。并不是性能簽渲染全綠就可以。和16毫秒刷新的要求差的還挺多的。
然后,你需要保證你的同事寫的別的組件不拖你后腿(我開玩笑的!真的),整個(gè)頁面的計(jì)算和渲染都必須控制在8.33毫秒內(nèi)。當(dāng)然,性能簽錄了堆棧的。哪拖后腿搞哪就好,跟正常的前端性能調(diào)試沒啥區(qū)別。
這里需要承認(rèn),到寫這玩意兒為止,還是沒能保證應(yīng)用場(chǎng)景的整個(gè)頁面計(jì)算+渲染在8.3毫秒以內(nèi)。確實(shí),和用戶的硬件性能關(guān)聯(lián)還挺大的。但是盡可能提高性能還是得花些功夫。(反正至少我開發(fā)機(jī),調(diào)不到這個(gè)數(shù),我也不會(huì)上線,你們也看不著,哈哈哈哈哈)
開發(fā)環(huán)境錄屏。
這個(gè)完全是測(cè)主觀感受用的。上述都是理論、數(shù)據(jù)。實(shí)際主觀感受,絲滑程度,跟手程度,基本優(yōu)化完一個(gè)地方,就實(shí)際操作錄一版。逐幀播放??粗挠X得不對(duì)勁逐幀播放看一下。

遺留問題:GC
眾所周知,瀏覽器GC。。。行吧 我不說了,就是會(huì)卡一下。有感知的卡一下。目前還沒有特別好的解法。不過大致的思路是,盡可能縮短GC時(shí)間。畢竟GC過程在清理無用的內(nèi)存。也是順著節(jié)點(diǎn)往上找有沒有引用占得時(shí)間長。那么盡可能的,少制造垃圾。。只是解題思路,這玩意,沒真優(yōu)化完,不敢說確保有效。有啥新想法到時(shí)候再寫吧。
最后:更新完應(yīng)該不會(huì)在現(xiàn)有功能上先用,應(yīng)該是新功能上用。收一波數(shù)據(jù),再改現(xiàn)有的視頻圈點(diǎn)批注。

依舊,群號(hào),答案自己查
711929228?