WEB運用中動畫很主要
不管是web運用照樣原生運用,也不論是PC端運用照樣挪動端運用,動畫都扮演了一個主要的角色。
只管動畫並不會增添運用的現實動能,但一個好的動畫,一個流通且文雅,挑選在適當機遇湧現的動畫,能為運用增色不少,能很好的指導用戶舉行下一步操縱,讓運用的場景切換更合理。一個小小的細節動畫,就可以幾個條理的提拔運用的用戶體驗。
舉個簡樸的例子,運用中最罕見的頁面間切換,假如缺乏切換動畫,那就會是這個模樣:
異常僵硬,頁面的湧現顯得異常高聳。作為對照,我們可以看下增添了動畫的頁面切換是什麼模樣的呢:
增添了用戶預期,也能較好的提醒用戶頁面的層級關聯。
再舉個彈窗的例子,先放兩個對照圖,左側是無動畫的結果,右側是增添完動畫的結果:
動畫雖然沒有增添什麼現實可見的功用,然則經由歷程對照,不難發明,動畫的增添,讓彈窗的湧現顯得膩滑天然,讓頁面的場景替代有一個歷程,削減高聳感,讓用戶體驗感覺增色不少不是嗎?
固然有可以因為錄製的題目,動畫結果不是很明顯,你可以有差別的意見。
動畫完成的基礎道理
web運用的基礎骨架是DOM,恰是一個個的DOM節點,構建出web運用,換句話說,就是web運用顯現出來的模樣是DOM決議的(固然這裏把CSS款式,歸結為了DOM的一部份)。所以動畫的完成,從本質上來講,就是操縱DOM:讓DOM在差別的時刻節點,在差別的位置、有差別的大小、透明度、顯現差別的背景色等,而且讓這類變化一連起來,則構成了我們能視察到的動畫。
基於web動畫完成的基礎道理,在我們直接操縱DOM的時期,完成動畫相對我們來講,異常直觀——只需曉得怎樣操縱DOM即可。比方須要完成一個黑色背景的div方塊,1s內從離左側距100px的位置,挪動到離左側距200px的位置,則我們只須要每秒控制該div的left
值增添(200-100)/60px
即可完成一個勻速的動畫結果。怎樣,很簡樸吧。
上述動畫完成的體式格局,我們稱為JS動畫。是由JS劇本邏輯,動態的轉變DOM的CSS屬性值。
CSS3中,增添了動畫的完成的設計,所以web中第二種動畫完成,被我們稱為CSS動畫
。CSS動畫,最主要的幾個CSS屬性是: transition,transform,animation,因為與本文的主題不是密切相干,此處就不做細緻引見,有興緻可以自行搜刮相干文章查閱。
MV*情勢下的動畫完成
這裏的MV*情勢我們不展開說,特指React中動畫的完成。React因為加入了假造DOM等諸多特徵,而且其開闢情勢讓開闢者不須要或許不引薦直接接觸到實在的DOM構造。所以其動畫完成,與通例的開闢體式格局下的動畫完成,存在肯定得差別。
動畫的完成終究肯定是落地到操縱DOM,MV*情勢的框架則是數據驅動DOM的展現。假如我們因為動畫完成的須要,對DOM的操縱湧現題目,勢必會影響到運用的相干操縱。我們先不去深切探討怎樣處理這個題目,先看看React官方和社區對這個題目是怎樣處理的,讓我們能先給我們的React運用增添上須要的動畫。
由淺及深,我們先學會怎樣運用,再去相識內部的完成道理,從而依據運用本身需求,能完成自定義的動畫,能完成更加龐雜的交互動畫等。
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.x
API供應的。
另一個經常使用的React動畫庫是react-motion
。該庫具有異常棒的特徵,可以創建出異常細緻的動畫,接着往下看,會引見下基礎的運用,然後參照其官方文檔,置信可以完成出大多數你想要的動畫的。
1. ReactCSSTransitionGroup
react-addons-css-transition-group
,平常稱其export
的組件為ReactCSSTransitionGroup
,它供應一種聲明的體式格局來定義CSS動畫
。ReactCSSTransitionGroup
的子組件必需大於或即是1個,不能為空。
ReactCSSTranstionGroup
組件暴露的屬性有:
- transitionAppear/transitionEnter/transitionLeave: Boolean 範例,標識是不是開啟動畫
- transitionAppearTimeout/transitionEnterTimeout/transitionLeaveTimeout: 定義各階段動畫的時長
- transitionName:自定義各階段動畫的 CSS 款式名
- component: ReactCSSTranstion以什麼組件包裹(wrap)子組件,默以為
span
,可所以React Element 。
我們以 todo-list 為例,看看ReactCSSTransitionGroup
怎樣運用。因為篇幅限定,todo-list 相干的營業代碼疏忽,可以在這裏檢察完全代碼。以下是動畫部份代碼:
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 (
<div>
... ,
<div className="list">
<ReactCSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}
component="div"
>
{
items.map((item)=>(
<div key={item} className="item">{item}</div>
))
}
</ReactCSSTransitionGroup>
</div>
</div>
)
}
}
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款式中定義的動畫時長對應上。
關於react-addons-css-transition-group
,知乎這篇文章CSS 動畫及其在 React 中的運用有較為細緻的引見。
2. ReactTransitionGroup
react-addons-transition-group
是react-addons-css-transition-group
的low-level
API,其供應動畫實行中須要的各生命周期函數:
- componentWillAppear(): componentDidMount時實行, 襯着
TransitionGroup
時實行而且只會實行一次。 - componentDidAppear(): 傳給componentWillAppear的
callback
實行后實行。 - componentWillEnter(): componentDidMount時實行,子組件增添進
TransitionGroup
時實行。 - componentDidEnter(): 傳給componentWillEnter的
callback
實行后實行。 - componentWillLeave(): 子組件從
TransitionGroup
中移除時實行,Though the child has been removed, TransitionGroup will keep it in the DOM until callback is called.
- componentDidLeave(): componentWillLeave的
callback
實行后實行。通常情況下與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 (
<div ref={this.getRef} onClick={onRemove} className={styles.item}>
{text}
</div>
)
}
}
export class App extends Component{
... ,
render(){
const { items } = this.state ;
return (
<div>
... ,
<div className="list">
{
items.map((item,i)=>(
<Item key={item} text={item} ...otherProps />
))
}
</div>
</div>
)
}
}
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
,我們須要本身去控制組件的動畫生命周期,增添了肯定的龐雜度,然則對自動以動畫,又能供應更好的天真度。可以依據營業場景,挑選適宜的Group
,去完成我們的需求。
通常情況下,我們用ReactCSSTransitionGroup
就可以滿足較多的營業場景了,而且從完成上會輕易許多。
3. ReactMotion
react-motion
供應了5個API接口:
- spring: 動畫天生要領
- Motion: React 組件
- StaggeredMotion: React 組件
- TransitionMotion: React 組件
- presets: spring要領的設置項
跟其他React動畫庫一樣,react-motion
也供應React組件去包裹須要動畫的營業組件。个中:
-
Motion
組件只接收一個children
組件 -
StaggeredMotion
組件接收一組children
組件 -
TranstionMotion
組件可以支撐其children
組件mounting
和unmounting
定義動畫
仍然是 todo-list 的例子,react-motion
的完成也異常簡樸:
import React,{ Component } from 'react' ;
import { Motion , spring } from 'react-motion';
export default class App extends Component{
... ,
render(){
const { items } = this.state ;
return (
<div>
... ,
<div className="list">
{
items.map((item)=>{
return (
<Motion defaultStyle={{opacity:0}} style={{opacity:spring(1)}}>
{
interpolatingStyle => (
<div
key={item}
className="item"
style={interpolatingStyle}
>
{item}
</div>
)
}
</Motion>
)
})
}
</div>
</div>
)
}
}
經由歷程上述簡樸的代碼,即可完成每一個Item在mounting
的時刻漸現的結果。
另一方面,視察上述完成,我們不難發明,react-motion
不單單議支撐React web運用,它應當也能輕鬆的運用到React-Native中。因為其React組件只是依據供應的defaultStyle
及style
屬性,天生動畫的數據,營業運用中拿到天生的數據后依據須要增添須要動畫的組件款式。react-motion
在web運用中機能表現較為可觀,在React-Native運用中的機能表現,有待我們調研。
除了上述簡樸的動畫運用,react-motion
在龐雜動畫的完成方面,表現異常優勝。下面的動圖是react-motion
完成的一個動畫演示:
這個示例展現了部份react-motion
的才能,更多關於react-motion
的運用就讓我們一同去發明吧。
結語
固然React動畫相干的庫另有許多,本文不過量引見。經由歷程上述對這些庫的運用做簡樸引見,筆者願望經由歷程對它們完成舉行剖析,讓讀者能更好的明白與控制,能對React動畫的完成道理和完成體式格局,有更加清楚的熟悉。
然則對相干代碼的研討,深切度還不足以給讀者朋儕分享,所以臨時留坑,後續會將相干源碼的進修,記錄在文檔React動畫的完成道理一文中,並設計增添從零開始,完成React動畫文章作為進修效果。假如對React動畫保有興緻,可以關注這兩篇文章的後續內容。