摘要:因為其組件只是根據(jù)提供的及屬性,生成動畫的數(shù)據(jù),業(yè)務(wù)應(yīng)用中拿到生成的數(shù)據(jù)后根據(jù)需要添加需要動畫的組件樣式。除了上述簡單的動畫應(yīng)用,在復(fù)雜動畫的實現(xiàn)方面,表現(xiàn)非常優(yōu)越。
WEB應(yīng)用中動畫很重要
不管是web應(yīng)用還是原生應(yīng)用,也不論是PC端應(yīng)用還是移動端應(yīng)用,動畫都扮演了一個重要的角色。
盡管動畫并不會添加應(yīng)用的實際動能,但一個好的動畫,一個流暢且優(yōu)雅,選擇在恰當(dāng)時機出現(xiàn)的動畫,能為應(yīng)用增色不少,能很好的引導(dǎo)用戶進行下一步操作,讓應(yīng)用的場景切換更合理。一個小小的細(xì)節(jié)動畫,就能幾個層次的提升應(yīng)用的用戶體驗。
舉個簡單的例子,應(yīng)用中最常見的頁面間切換,如果缺少切換動畫,那就會是這個樣子:
非常生硬,頁面的出現(xiàn)顯得非常突兀。作為對比,我們可以看下添加了動畫的頁面切換是什么樣子的呢:
增加了用戶預(yù)期,也能較好的提示用戶頁面的層級關(guān)系。
再舉個彈窗的例子,先放兩個對比圖,左邊是無動畫的效果,右邊是添加完動畫的效果:
動畫雖然沒有添加什么實際可見的功能,但是通過對比,不難發(fā)現(xiàn),動畫的添加,讓彈窗的出現(xiàn)顯得平滑自然,讓頁面的場景替換有一個過程,減少突兀感,讓用戶體驗感受增色不少不是嗎?
當(dāng)然有可能因為錄制的問題,動畫效果不是很明顯,你可能有不同的看法。動畫實現(xiàn)的基本原理
web應(yīng)用的基本骨架是DOM,正是一個個的DOM節(jié)點,構(gòu)建出web應(yīng)用,換句話說,就是web應(yīng)用呈現(xiàn)出來的樣子是DOM決定的(當(dāng)然這里把CSS樣式,歸納為了DOM的一部分)。所以動畫的實現(xiàn),從本質(zhì)上來講,就是操作DOM:讓DOM在不同的時間節(jié)點,在不同的位置、有不同的大小、透明度、呈現(xiàn)不同的背景色等,并且讓這種變化連續(xù)起來,則構(gòu)成了我們能觀察到的動畫。
基于web動畫實現(xiàn)的基本原理,在我們直接操作DOM的時代,實現(xiàn)動畫相對我們來說,非常直觀——只要知道怎么操作DOM即可。比如需要實現(xiàn)一個黑色背景的div方塊,1s內(nèi)從離左邊距100px的位置,移動到離左邊距200px的位置,則我們只需要每秒控制該div的left值增加(200-100)/60px即可實現(xiàn)一個勻速的動畫效果。怎么樣,很簡單吧。
上述動畫實現(xiàn)的方式,我們稱為JS動畫。是由JS腳本邏輯,動態(tài)的改變DOM的CSS屬性值。
CSS3中,添加了動畫的實現(xiàn)的方案,所以web中第二種動畫實現(xiàn),被我們稱為CSS動畫。CSS動畫,最主要的幾個CSS屬性是: transition,transform,animation,由于與本文的主題不是密切相關(guān),此處就不做詳細(xì)介紹,有興趣可以自行搜索相關(guān)文章查閱。
MV*模式下的動畫實現(xiàn)這里的MV*模式我們不展開說,特指React中動畫的實現(xiàn)。React由于加入了虛擬DOM等諸多特性,并且其開發(fā)模式讓開發(fā)者不需要或者不推薦直接接觸到真實的DOM結(jié)構(gòu)。所以其動畫實現(xiàn),與常規(guī)的開發(fā)方式下的動畫實現(xiàn),存在一定得差異。
動畫的實現(xiàn)最終一定是落地到操作DOM,MV*模式的框架則是數(shù)據(jù)驅(qū)動DOM的展示。如果我們因為動畫實現(xiàn)的需要,對DOM的操作出現(xiàn)問題,勢必會影響到應(yīng)用的相關(guān)操作。我們先不去深入探討怎么解決這個問題,先看看React官方和社區(qū)對這個問題是怎么解決的,讓我們能先給我們的React應(yīng)用添加上需要的動畫。
由淺及深,我們先學(xué)會怎么使用,再去了解內(nèi)部的實現(xiàn)原理,從而根據(jù)應(yīng)用自身需求,能實現(xiàn)自定義的動畫,能實現(xiàn)更為復(fù)雜的交互動畫等。
React中我們怎么添加動畫React的動畫庫中,比較常用的是react-addons-css-transition-group、react-addons-transition-group 以及react-motion 。其中, react-addons-css-transition-group是react-addons-transition-group的High-Level API庫,react-addons-css-transtion-group是基于react-addons-transition-group的上層封裝。目前react-addons-css-transition-group和react-addons-transition-group合并成一個庫,叫react-transition-group。
react-transition-group@v1.x版本中的API, 基本保持與兩個多帶帶庫的API形式一致,但@v2.x版本中的API變化較大,并不能完全切換,這個需要注意。本文的示例是以獨立庫,也就是類react-transtion-group@v1.xAPI提供的。
另一個常用的React動畫庫是react-motion 。該庫擁有非常棒的特性,能夠創(chuàng)建出非常細(xì)膩的動畫,接著往下看,會介紹下基本的使用,然后參照其官方文檔,相信可以實現(xiàn)出大多數(shù)你想要的動畫的。
1. ReactCSSTransitionGroupreact-addons-css-transition-group,一般稱其export的組件為ReactCSSTransitionGroup,它提供一種聲明的方式來定義CSS動畫。ReactCSSTransitionGroup的子組件必須大于或等于1個,不能為空。
ReactCSSTranstionGroup組件暴露的屬性有:
transitionAppear/transitionEnter/transitionLeave: Boolean 類型,標(biāo)識是否開啟動畫
transitionAppearTimeout/transitionEnterTimeout/transitionLeaveTimeout: 定義各階段動畫的時長
transitionName:自定義各階段動畫的 CSS 樣式名
component: ReactCSSTranstion以什么組件包裹(wrap)子組件,默認(rèn)為span,可以是React Element 。
我們以 todo-list 為例,看看ReactCSSTransitionGroup怎么使用。由于篇幅限制,todo-list 相關(guān)的業(yè)務(wù)代碼忽略,可以在這里查看完整代碼。以下是動畫部分代碼:
index.js:
import React , { Component } from "react" ; import ReactCSSTranstionGroup from "react-addons-css-transition-group" ; export default class App extends Component{ ... , render(){ const { items } = this.state ; return (... ,) } }{ items.map((item)=>( {item})) }
style.css:
.example-enter { opacity: 0.01; } .example-enter.example-enter-active { opacity: 1; transition: opacity 500ms ease-in; } .example-leave { opacity: 1; } .example-leave.example-leave-active { opacity: 0.01; transition: opacity 300ms ease-in; }
有兩點需要注意:
每個子組件必須有key,這樣ReactCSSTrasntionGroup才能正確的mounting和unmounting子組件。
自定義的動畫時長,需要與CSS樣式中定義的動畫時長對應(yīng)上。
關(guān)于react-addons-css-transition-group,知乎這篇文章CSS 動畫及其在 React 中的應(yīng)用有較為詳細(xì)的介紹。
2. ReactTransitionGroupreact-addons-transition-group是react-addons-css-transition-group的low-level API,其提供動畫執(zhí)行中需要的各生命周期函數(shù):
componentWillAppear(): componentDidMount時執(zhí)行, 渲染TransitionGroup時執(zhí)行并且只會執(zhí)行一次。
componentDidAppear(): 傳給componentWillAppear的callback執(zhí)行后執(zhí)行。
componentWillEnter(): componentDidMount時執(zhí)行,子組件添加進TransitionGroup時執(zhí)行。
componentDidEnter(): 傳給componentWillEnter的callback執(zhí)行后執(zhí)行。
componentWillLeave(): 子組件從TransitionGroup中移除時執(zhí)行,Though the child has been removed, TransitionGroup will keep it in the DOM until callback is called.
componentDidLeave(): componentWillLeave的callback執(zhí)行后執(zhí)行。通常情況下與ComponentWillUnmount的時機一致。
那我們看看,同樣以 todo-list 為例, ReactTransitionGroup需要怎么做呢?
index.js:
import React,{ Component } from "react" ; import ReactTransitionGroup from "react-addons-transition-group" ; class Item extends Component{ // 獲取組件真實DOM getRef(ref){ this.ref=ref ; } componentWillEnter(callback){ this.ref.classList.add("example-enter") ; setTimeout(()=>{ callback() ; },500) ; } componentDidEnter(){ this.ref.classList.add("example-enter-active") ; } componentWillLeave(){ this.ref.classList.remove("example-enter","example-enter-active") ; this.ref.classList.add("example-leave-active","example-leave") ; setTimeout(()=>{ callback() ; },300) ; } render(){ const { text , onRemove } = this.props ; return ({text}) } } export class App extends Component{ ... , render(){ const { items } = this.state ; return (... ,) } }{ items.map((item,i)=>(- )) }
style.css:
.example-enter { opacity: 0.01; } .example-enter.example-enter-active { opacity: 1; transition: opacity 500ms ease-in; } .example-leave { opacity: 1; } .example-leave.example-leave-active { opacity: 0.01; transition: opacity 300ms ease-in; }
相比于ReactCSSTransitionGroup,我們需要自己去控制組件的動畫生命周期,增加了一定的復(fù)雜度,但是對自動以動畫,又能提供更好的靈活度??梢愿鶕?jù)業(yè)務(wù)場景,選擇合適的Group,去實現(xiàn)我們的需求。
通常情況下,我們用ReactCSSTransitionGroup就能滿足較多的業(yè)務(wù)場景了,并且從實現(xiàn)上會容易很多。
3. ReactMotionreact-motion提供了5個API接口:
spring: 動畫生成方法
Motion: React 組件
StaggeredMotion: React 組件
TransitionMotion: React 組件
presets: spring方法的配置項
跟其他React動畫庫一樣,react-motion也提供React組件去包裹需要動畫的業(yè)務(wù)組件。其中:
Motion組件只接受一個children組件
StaggeredMotion組件接受一組children組件
TranstionMotion組件可以支持其children組件mounting和unmounting定義動畫
仍然是 todo-list 的例子,react-motion的實現(xiàn)也非常簡單:
import React,{ Component } from "react" ; import { Motion , spring } from "react-motion"; export default class App extends Component{ ... , render(){ const { items } = this.state ; return (... ,) } }{ items.map((item)=>{ return ({ interpolatingStyle => ( ) }) }{item}) }
通過上述簡單的代碼,即可實現(xiàn)每個Item在mounting的時候漸現(xiàn)的效果。
另一方面,觀察上述實現(xiàn),我們不難發(fā)現(xiàn),react-motion不僅僅支持React web應(yīng)用,它應(yīng)該也能輕松的應(yīng)用到React-Native中。因為其React組件只是根據(jù)提供的defaultStyle及style屬性,生成動畫的數(shù)據(jù),業(yè)務(wù)應(yīng)用中拿到生成的數(shù)據(jù)后根據(jù)需要添加需要動畫的組件樣式。react-motion在web應(yīng)用中性能表現(xiàn)較為可觀,在React-Native應(yīng)用中的性能表現(xiàn),有待我們調(diào)研。
除了上述簡單的動畫應(yīng)用,react-motion在復(fù)雜動畫的實現(xiàn)方面,表現(xiàn)非常優(yōu)越。下面的動圖是react-motion實現(xiàn)的一個動畫演示:
這個示例展示了部分react-motion的能力,更多關(guān)于react-motion的應(yīng)用就讓我們一起去發(fā)現(xiàn)吧。
結(jié)語當(dāng)然React動畫相關(guān)的庫還有很多,本文不過多介紹。通過上述對這些庫的使用做簡單介紹,筆者希望通過對它們實現(xiàn)進行分析,讓讀者能更好的理解與掌握,能對React動畫的實現(xiàn)原理和實現(xiàn)方式,有更為清晰的認(rèn)識。
但是對相關(guān)代碼的研究,深入度還不足以給讀者朋友分享,所以暫時留坑,后續(xù)會將相關(guān)源碼的學(xué)習(xí),記錄在文檔React動畫的實現(xiàn)原理一文中,并計劃添加從零開始,實現(xiàn)React動畫文章作為學(xué)習(xí)成果。如果對React動畫保有興趣,可以關(guān)注這兩篇文章的后續(xù)內(nèi)容。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/94656.html
摘要:大家可以嘗試使用的,配置一個合適的勁度系數(shù)和空氣阻力。所做的事,只不過自己實現(xiàn)了一套緩動函數(shù)。 根據(jù)經(jīng)典力學(xué)的觀點,世界上所有的原子每時每刻仿佛都會根據(jù)當(dāng)前速度、受力和位置計算出下一刻的速度、受力和位置。上帝有一臺超級計算機嗎?非也,反而計算機是我們利用原子的這些特性拼裝出來的?,F(xiàn)在,我們卻要用計算機,像上帝那樣,再造一個世界。 我不知道這個世界上有沒有仿世學(xué),但是既然動畫是要模仿現(xiàn)實...
摘要:父組件向子組件之間非常常見,通過機制傳遞即可。我們應(yīng)該聽說過高階函數(shù),這種函數(shù)接受函數(shù)作為輸入,或者是輸出一個函數(shù),比如以及等函數(shù)。在傳遞數(shù)據(jù)的時候,我們可以用進一步提高性能。 本文主要談自己在react學(xué)習(xí)的過程中總結(jié)出來的一些經(jīng)驗和資源,內(nèi)容邏輯參考了深入react技術(shù)棧一書以及網(wǎng)上的諸多資源,但也并非完全照抄,代碼基本都是自己實踐,主要為平時個人學(xué)習(xí)做一個總結(jié)和參考。 本文的關(guān)鍵...
摘要:父組件向子組件之間非常常見,通過機制傳遞即可。我們應(yīng)該聽說過高階函數(shù),這種函數(shù)接受函數(shù)作為輸入,或者是輸出一個函數(shù),比如以及等函數(shù)。在傳遞數(shù)據(jù)的時候,我們可以用進一步提高性能。 本文主要談自己在react學(xué)習(xí)的過程中總結(jié)出來的一些經(jīng)驗和資源,內(nèi)容邏輯參考了深入react技術(shù)棧一書以及網(wǎng)上的諸多資源,但也并非完全照抄,代碼基本都是自己實踐,主要為平時個人學(xué)習(xí)做一個總結(jié)和參考。 本文的關(guān)鍵...
摘要:父組件向子組件之間非常常見,通過機制傳遞即可。我們應(yīng)該聽說過高階函數(shù),這種函數(shù)接受函數(shù)作為輸入,或者是輸出一個函數(shù),比如以及等函數(shù)。在傳遞數(shù)據(jù)的時候,我們可以用進一步提高性能。 本文主要談自己在react學(xué)習(xí)的過程中總結(jié)出來的一些經(jīng)驗和資源,內(nèi)容邏輯參考了深入react技術(shù)棧一書以及網(wǎng)上的諸多資源,但也并非完全照抄,代碼基本都是自己實踐,主要為平時個人學(xué)習(xí)做一個總結(jié)和參考。 本文的關(guān)鍵...
摘要:我模仿的應(yīng)用構(gòu)建了一個開閉卡片的輪播效果作為技術(shù)演示它使用了及其動畫庫當(dāng)人們聽到后第一反應(yīng)會覺得它運行緩慢這是因為一般人會去這樣解釋它允許你通過構(gòu)建你的應(yīng)用程序而人們會認(rèn)為瀏覽器中運行的性能并不夠好但事實是它采用的全部都是原生界面元素但你通 我模仿 Facebook 的 Paper 應(yīng)用構(gòu)建了一個開閉卡片的輪播效果作為技術(shù)演示.它使用了 React Native 及其動畫庫. 當(dāng)人們聽...
閱讀 2467·2023-04-25 14:22
閱讀 3823·2021-11-15 18:12
閱讀 1360·2019-08-30 15:44
閱讀 3286·2019-08-29 15:37
閱讀 813·2019-08-29 13:49
閱讀 3521·2019-08-26 12:11
閱讀 974·2019-08-23 18:28
閱讀 1665·2019-08-23 14:55