摘要:因為其組件只是根據提供的及屬性,生成動畫的數據,業務應用中拿到生成的數據后根據需要添加需要動畫的組件樣式。除了上述簡單的動畫應用,在復雜動畫的實現方面,表現非常優越。
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.xAPI提供的。
另一個常用的React動畫庫是react-motion 。該庫擁有非常棒的特性,能夠創建出非常細膩的動畫,接著往下看,會介紹下基本的使用,然后參照其官方文檔,相信可以實現出大多數你想要的動畫的。
1. ReactCSSTransitionGroupreact-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 (... ,) } }{ 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樣式中定義的動畫時長對應上。
關于react-addons-css-transition-group,知乎這篇文章CSS 動畫及其在 React 中的應用有較為詳細的介紹。
2. ReactTransitionGroupreact-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 ({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,我們需要自己去控制組件的動畫生命周期,增加了一定的復雜度,但是對自動以動畫,又能提供更好的靈活度。可以根據業務場景,選擇合適的Group,去實現我們的需求。
通常情況下,我們用ReactCSSTransitionGroup就能滿足較多的業務場景了,并且從實現上會容易很多。
3. ReactMotionreact-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 (... ,) } }{ items.map((item)=>{ return ({ interpolatingStyle => ( ) }) }{item}) }
通過上述簡單的代碼,即可實現每個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動畫保有興趣,可以關注這兩篇文章的后續內容。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94656.html
摘要:大家可以嘗試使用的,配置一個合適的勁度系數和空氣阻力。所做的事,只不過自己實現了一套緩動函數。 根據經典力學的觀點,世界上所有的原子每時每刻仿佛都會根據當前速度、受力和位置計算出下一刻的速度、受力和位置。上帝有一臺超級計算機嗎?非也,反而計算機是我們利用原子的這些特性拼裝出來的。現在,我們卻要用計算機,像上帝那樣,再造一個世界。 我不知道這個世界上有沒有仿世學,但是既然動畫是要模仿現實...
摘要:我模仿的應用構建了一個開閉卡片的輪播效果作為技術演示它使用了及其動畫庫當人們聽到后第一反應會覺得它運行緩慢這是因為一般人會去這樣解釋它允許你通過構建你的應用程序而人們會認為瀏覽器中運行的性能并不夠好但事實是它采用的全部都是原生界面元素但你通 我模仿 Facebook 的 Paper 應用構建了一個開閉卡片的輪播效果作為技術演示.它使用了 React Native 及其動畫庫. 當人們聽...
閱讀 2288·2023-04-25 14:22
閱讀 3733·2021-11-15 18:12
閱讀 1293·2019-08-30 15:44
閱讀 3215·2019-08-29 15:37
閱讀 638·2019-08-29 13:49
閱讀 3454·2019-08-26 12:11
閱讀 866·2019-08-23 18:28
閱讀 1581·2019-08-23 14:55