Đối với React Native, khi bạn muốn tạo animation thì Animated API là cách hữu hiệu nhất.
Có ba method chủ yếu mà bạn sẽ dùng để tạo ra animation
Animated.timing()
– Kết nối quãng thời gian với giá trị tuyến tínhAnimated.decay()
– Bắt đầu với một gia tốc nhất định sau đố giảm dần cho đến khi dừng lại.Animated.spring()
– Một model vật lýsingle-spring
đơn giản dựa vào Rebound và Origami. Kiểm tra trạng thái gia tốc để tạo ra một chuyển động lỏng bồng bềnh khi giá trịtoValue
được update và có thể kết nối với nhau.
Chúng ta sẽ tìm hiểu chính về Animated.timing()
và Animated.spring()
vì chúng có độ phổ biến cao nhất.
Cùng với ba method trên thì có ba cách để gọi những animation này. Chúng ta sẽ tìm hiểu cả ba cách này nữa.
Animated.parallel()
– Bắt đầu với một array các animation cùng một lúc.Animated.sequence()
– Bắt đầu với một array các animation theo thứ tự, đợi khi cái này xong cái khác mới được bắt đầu. Nếu animation hiện tại bị dừng, sẽ không có animation nào được bắt đầu nữa.Animated.stagger()
– Giống vớiAnimated.parallel()
những cho phép chúng ta thêm delay vào giữa các animation.
1. Animated.timing()
Animation đầu tiên mà chúng ta sẽ tạo là animation xoay này bằng cách dùng Animated.timing()
.
1 2 3 4 5 6 7 8 9 10 | Animated<span class="token punctuation">.</span><span class="token function">timing</span><span class="token punctuation">(</span> someValue<span class="token punctuation">,</span> <span class="token punctuation">{</span> toValue<span class="token punctuation">:</span> number<span class="token punctuation">,</span> duration<span class="token punctuation">:</span> number<span class="token punctuation">,</span> easing<span class="token punctuation">:</span> easingFunction<span class="token punctuation">,</span> delay<span class="token punctuation">:</span> number <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
Loại animation vĩnh viễn này rất phù hợp để tạo ra các icon loading. Để bắt đầu đương nhiên chúng ta cần phải tạo project React Native rồi.
1 2 3 | react<span class="token operator">-</span>native init animations cd animations |
Trong folder này, mở ra index.android.js
hoặc index.ios.js
file
Bây giờ chúng ta đã có một project mới được tạo, điều đầu tiên mà chúng ta cần làm đó là import Animated
,Image
và Easing
vào :
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">import</span> <span class="token punctuation">{</span> AppRegistry<span class="token punctuation">,</span> StyleSheet<span class="token punctuation">,</span> Text<span class="token punctuation">,</span> View<span class="token punctuation">,</span> Animated<span class="token punctuation">,</span> Image<span class="token punctuation">,</span> Easing <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-native'</span> |
Animated
là thư viện mà chúng ta cần để tạo ra animation.
Image
cần thiết để tạo ra ảnh trong UI
Easing
là module cho phép ta tạo ra các dạng tuyến tính như là linear, ease, quad, cubic, sin. elastic, bounce, back, benzier, in, out, inout
và nhiều thứ khác. Ở đây chúng ta sẽ sử dụng linear
.
Tiếp theo, chúng ta cần đặt một giá trị khởi tạo cho giá trị xoay :
1 2 3 4 5 | <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>spinValue <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Animated<span class="token punctuation">.</span>Value</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Chúng ta đặt spinValue
là giá trị mới của Animated.Value
và truyền 0 vào.
Tiếp theo chúng ta cần tạo ra một hàm spin và gọi hàm này trong componentDidMount
để cho nó chạy lúc load app.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token function">componentDidMount</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">spin</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">spin</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>spinValue<span class="token punctuation">.</span><span class="token function">setValue</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> Animated<span class="token punctuation">.</span><span class="token function">timing</span><span class="token punctuation">(</span> <span class="token keyword">this</span><span class="token punctuation">.</span>spinValue<span class="token punctuation">,</span> <span class="token punctuation">{</span> toValue<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> duration<span class="token punctuation">:</span> <span class="token number">4000</span><span class="token punctuation">,</span> easing<span class="token punctuation">:</span> Easing<span class="token punctuation">.</span>linear <span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">spin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
hàm spin()
sẽ làm những việc sau đây :
- Đặt
this.spinValue
về lại 0 - Gọi
Animated.timing
và đặt giá trịthis.spinValue
thành 1 trong khoảng 4000 miliseconds với easing là linear. - Gọi
start()
ở method theo sau vào đưa vàothis.spin()
vào trong callback để gọi vòng lặp vĩnh cửu.
Tiếp theo chúng ta cần phải render nó ra :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> spin <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>spinValue<span class="token punctuation">.</span><span class="token function">interpolate</span><span class="token punctuation">(</span><span class="token punctuation">{</span> inputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> outputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'0deg'</span><span class="token punctuation">,</span> <span class="token string">'360deg'</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>View style<span class="token operator">=</span><span class="token punctuation">{</span>styles<span class="token punctuation">.</span>container<span class="token punctuation">}</span><span class="token operator">></span> <span class="token operator"><</span>Animated<span class="token punctuation">.</span>Image style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> width<span class="token punctuation">:</span> <span class="token number">227</span><span class="token punctuation">,</span> height<span class="token punctuation">:</span> <span class="token number">200</span><span class="token punctuation">,</span> transform<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>rotate<span class="token punctuation">:</span> spin<span class="token punctuation">}</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">}</span> source<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span>uri<span class="token punctuation">:</span> <span class="token string">'https://s3.amazonaws.com/media-p.slid.es/uploads/alexanderfarennikov/images/1198519/reactjs.png'</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>View<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Cuối cùng là style component ra giữa.
1 2 3 4 5 6 7 8 | <span class="token keyword">const</span> styles <span class="token operator">=</span> StyleSheet<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">{</span> container<span class="token punctuation">:</span> <span class="token punctuation">{</span> flex<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> justifyContent<span class="token punctuation">:</span> <span class="token string">'center'</span><span class="token punctuation">,</span> alignItems<span class="token punctuation">:</span> <span class="token string">'center'</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
2. Một vài ví dụ nữa về Animated.timing
Chúng ta biết được phần cơ bản của Animated.timing
, bây giờ hãy xem thêm một vài ví dụ nữa liên quan đến interpolate
(giá trị nội suy) và tạo ra chúng.
Trong ví dụ tiếp theo, chúng ta sẽ tạo ra giá trị animation đơn lẻ, và dùng chúng để tạo ra nhiều animation theo các style sau :
- marginLeft
- opacity
- fontSize
- rotateX
Điều đầu tiên mà chúng ta vẫn phải làm đó là tạo giá trị khởi tạo.
1 2 3 4 5 | <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>animatedValue <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Animated<span class="token punctuation">.</span>Value</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Sau đó tạo ra hàm animation trong componentDidMount()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token function">componentDidMount</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">animate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">animate</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>animatedValue<span class="token punctuation">.</span><span class="token function">setValue</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> Animated<span class="token punctuation">.</span><span class="token function">timing</span><span class="token punctuation">(</span> <span class="token keyword">this</span><span class="token punctuation">.</span>animatedValue<span class="token punctuation">,</span> <span class="token punctuation">{</span> toValue<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> duration<span class="token punctuation">:</span> <span class="token number">2000</span><span class="token punctuation">,</span> easing<span class="token punctuation">:</span> Easing<span class="token punctuation">.</span>linear <span class="token punctuation">}</span> <span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">animate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
trong hàm render, chúng ta tạo 5 giá trị nội suy khác nhau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> marginLeft <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>animatedValue<span class="token punctuation">.</span><span class="token function">interpolate</span><span class="token punctuation">(</span><span class="token punctuation">{</span> inputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> outputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">300</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> opacity <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>animatedValue<span class="token punctuation">.</span><span class="token function">interpolate</span><span class="token punctuation">(</span><span class="token punctuation">{</span> inputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> outputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> movingMargin <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>animatedValue<span class="token punctuation">.</span><span class="token function">interpolate</span><span class="token punctuation">(</span><span class="token punctuation">{</span> inputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> outputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">300</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> textSize <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>animatedValue<span class="token punctuation">.</span><span class="token function">interpolate</span><span class="token punctuation">(</span><span class="token punctuation">{</span> inputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> outputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">18</span><span class="token punctuation">,</span> <span class="token number">32</span><span class="token punctuation">,</span> <span class="token number">18</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> rotateX <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>animatedValue<span class="token punctuation">.</span><span class="token function">interpolate</span><span class="token punctuation">(</span><span class="token punctuation">{</span> inputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> outputRange<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'0deg'</span><span class="token punctuation">,</span> <span class="token string">'180deg'</span><span class="token punctuation">,</span> <span class="token string">'0deg'</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token operator">...</span> <span class="token punctuation">}</span> |
interpolate
chó phép chúng ta dùng this.animatedValue
theo nhiều cách khác nhau. Vì giá trị của nó chỉ có từ 0 đến 1 nên chúng ta có thể thay đổi nó theo nhiều giá trị khác nhau cho các style khác nhau như opacity, margin, text size, rotation.
Sau đó chúng ta return như sau :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>View style<span class="token operator">=</span><span class="token punctuation">{</span>styles<span class="token punctuation">.</span>container<span class="token punctuation">}</span><span class="token operator">></span> <span class="token operator"><</span>Animated<span class="token punctuation">.</span>View style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> marginLeft<span class="token punctuation">,</span> height<span class="token punctuation">:</span> <span class="token number">30</span><span class="token punctuation">,</span> width<span class="token punctuation">:</span> <span class="token number">40</span><span class="token punctuation">,</span> backgroundColor<span class="token punctuation">:</span> <span class="token string">'red'</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>Animated<span class="token punctuation">.</span>View style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> opacity<span class="token punctuation">,</span> marginTop<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> height<span class="token punctuation">:</span> <span class="token number">30</span><span class="token punctuation">,</span> width<span class="token punctuation">:</span> <span class="token number">40</span><span class="token punctuation">,</span> backgroundColor<span class="token punctuation">:</span> <span class="token string">'blue'</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>Animated<span class="token punctuation">.</span>View style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> marginLeft<span class="token punctuation">:</span> movingMargin<span class="token punctuation">,</span> marginTop<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> height<span class="token punctuation">:</span> <span class="token number">30</span><span class="token punctuation">,</span> width<span class="token punctuation">:</span> <span class="token number">40</span><span class="token punctuation">,</span> backgroundColor<span class="token punctuation">:</span> <span class="token string">'orange'</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>Animated<span class="token punctuation">.</span>Text style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> fontSize<span class="token punctuation">:</span> textSize<span class="token punctuation">,</span> marginTop<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> color<span class="token punctuation">:</span> <span class="token string">'green'</span><span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">></span> Animated Text<span class="token operator">!</span> <span class="token operator"><</span><span class="token operator">/</span>Animated<span class="token punctuation">.</span>Text<span class="token operator">></span> <span class="token operator"><</span>Animated<span class="token punctuation">.</span>View style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> transform<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>rotateX<span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> marginTop<span class="token punctuation">:</span> <span class="token number">50</span><span class="token punctuation">,</span> height<span class="token punctuation">:</span> <span class="token number">30</span><span class="token punctuation">,</span> width<span class="token punctuation">:</span> <span class="token number">40</span><span class="token punctuation">,</span> backgroundColor<span class="token punctuation">:</span> <span class="token string">'black'</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">></span> <span class="token operator"><</span>Text style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span>color<span class="token punctuation">:</span> <span class="token string">'white'</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">></span>Hello <span class="token keyword">from</span> TransformX<span class="token operator"><</span><span class="token operator">/</span>Text<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Animated<span class="token punctuation">.</span>View<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>View<span class="token operator">></span> <span class="token punctuation">)</span> |
Có thể thêm style vào
1 2 3 4 5 6 7 | <span class="token keyword">const</span> styles <span class="token operator">=</span> StyleSheet<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">{</span> container<span class="token punctuation">:</span> <span class="token punctuation">{</span> flex<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> paddingTop<span class="token punctuation">:</span> <span class="token number">150</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
Trên đây là phần 1 của bài hướng dẫn tạo animation, ở phần sau chúng ta sẽ tìm hiểu tiếp các cách tạo animation khác thú vị hơn.
REF: https://medium.com/react-native-training/react-native-animations-using-the-animated-api-ebe8e0669fae