[React Native] Guide - Phần 2 - Animations Part 1

Ở phần trước chúng ta đã tìm hiểu về cách điều khiển các sự kiện chạm trên màn hình. Trong phần này chúng ta sẽ tìm hiểu về một thành phần được ứng dụng khá nhiều trong hầu hết các ứng dụng đó là Animations

Part 1

Animations

Animations là một thành phần rất quan trọng để tạo nên sự tuyệt vời trong trải nghiệm người dùng. Ví như các vật thể cố định phải vượt qua quán tính đứng yên để bắt đầu di chuyển. Các đối tượng chuyển động có đà và hiếm khi dừng ngay lập tức. Animations cho phép bạn chuyển tải các chuyển động tương tự các vật thể trong giao diện của ứng dụng.

React Native cung cấp hai hệ thống animation: Animation để kiểm soát chi tiết và tương tác với các giá trị cụ thể và LayoutAnimation để di chuyển giao diện tổng thể.

Animated API

Animated API được thiết kế để làm cho nó rất dễ dàng để thể hiện một loạt các hình animation và interaction patterns bằng một cách rất hiệu quả. Animated tập trung vào các mối quan hệ khai báo inputs và outputs, với các phép biến đổi có thể cài đặt ở giữa và các quá trình start/stop để kiểm soát việc thực hiện animation dựa trên thời gian chạy.

Animated đưa ra dành cho 4 thành phần gồm có View, Text, ImageScrollView, nhưng bạn hoàn toàn có thể tạo ra những animation của riêng bạn để sử dụng.

Ví dụ dưới đây, một container view sẽ được hiển thị kiểu fade hi nó được xuất hiện lên trên màn hình:

// FadeInView.js
import React, { Component } from 'react';
import {
  Animated,
} from 'react-native';

class FadeInView extends Component {
  constructor(props) {
    super(props);
    this.state = {
      fadeAnim: new Animated.Value(0),          // Initial value for opacity: 0
    };
  }
  componentDidMount() {
    Animated.timing(                            // Animate over time
      this.state.fadeAnim,                      // The animated value to drive
      {
        toValue: 1,                             // Animate to opacity: 1, or fully opaque
      }
    ).start();                                  // Starts the animation
  }
  render() {
    return (
      <Animated.View                            // Special animatable View
        style={{
          ...this.props.style,
          opacity: this.state.fadeAnim,          // Bind opacity to animated value
        }}
      >
        {this.props.children}
      </Animated.View>
    );
  }
}

module.exports = FadeInView;

Bạn có thể sử dụng FadeInView tại nơi bạn đặt một View trong các thành phần giao diện, tương tự như dưới đây:

render() {
  return (
    <FadeInView style={{width: 250, height: 50, backgroundColor: 'powderblue'}}>
      <Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>Fading in</Text>
    </FadeInView>
  )
}

FadeInView

Bây giờ chúng ta sẽ tách nhỏ từng phần ra để phân tích có những gì ở đây. Trong hàm tạo của FadeInView, khởi tạo một Animated.Value được gọi trong fadeAnim như là một phần của state. Thuộc tính độ trong suốt của View được liên kết với giá trị của animated này. Bắt đầu khởi chạy, giá trị số này được định nghĩa chính xác và được sử dụng để cài đặt độ trong suốt.

Khi thành phần được khởi chạy, độ trong suốt được cài đặt bằng 0. Sau đó, một animation đơn giản sẽ được khởi chạy trong fadeAnim. Trong khi đó, nó sẽ chạy tất cả những thành phần có liên quan (trong trường hợp này thì chỉ có độ trong suốt của View) trên mỗi frame như là giá trị của animation và kết thúc sẽ là giá trị 1.

Cách cài đặt này là một cách làm đơn giản và nhanh hơn so với cách gọi setState và thực hiện render lại. Bởi vì toàn bộ config đã được định nghĩa, chúng ta sẽ có thể thực hiện tối ưu hoá và chạy animation trên một thread có độ ưu tiên cao.

Cấu hình animations

Animation có nhiều hình thức để cấu hình. Tùy chỉnh và các chức năng nới lỏng được xác định trước, delays, durations, decay factors, spring constants, và nhiều thứ khác có thể được tinh chỉnh tùy thuộc vào loại animation.

Animated cung cấp một số loại hình animation, một trong những loại animation thường được sử dụng nhất là Animated.timing(). Nó hỗ trợ cài đặt các giá trị một cách đơn giản hoặc bạn cũng có thể cấu hình cho riêng mình theo cách của bạn.

Mặc định, timing sẽ sử dùng đường cong easeInOut để thực hiện chuyển động từng bước một từ thấp nhất đến tốc độ cao nhất cho tới khi dừng lại. Bạn có thể định nghĩa cụ thể các hành động khác một cách dễ dàng bằng cách implement tham số easing. Tùy chỉnh lại duration hoặc delay trước khi animation được start, đó là những tham số đã được hỗ trợ.

Ví dụ, nếu như bạn muốn chạy một animation trong khoảng thời gian 2 giây cho một đối tượng nhỏ trước khi nó di chuyển đến vị trí cuối cùng, bạn có thể cài đặt như đoạn code dưới đây:

Animated.timing(
  this.state.xPosition,
  {
    toValue: 100,
    easing: Easing.back,
    duration: 2000,
  }                              
).start();

Hãy tìm kiếm thêm các cài đặt ở đây Configuring animation của Animated API để có thể học thêm về rất nhiều các tham số khác để cấu hình cho một animation.

Tự tạo các animation

Animation có thể được biên dịch và chạy trong hàng đợi hoặc chạy song song với nhau. Hàng đợi animation có thể chạy các animation tiếp theo sau khi animation trước vừa kết thúc. Hoặc cũng có thể cài đặt để animation sau chạy với một khoảng thời gian chờ đợi sau khi animation trước kết thúc. Animated API cung cấp các phương thức như sequence()delay(), mỗi một animation sẽ được nhận như một mảng và được thực hiện một cách tự động bằng cách gọi đến start()/stop() như là một điều bắt buộc.

Ví dụ:

Animated.sequence([            // decay, then spring to start and twirl
  Animated.decay(position, {   // coast to a stop
    velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release
    deceleration: 0.997,
  }),
  Animated.parallel([          // after decay, in parallel:
    Animated.spring(position, {
      toValue: {x: 0, y: 0}    // return to start
    }),
    Animated.timing(twirl, {   // and twirl
      toValue: 360,
    }),
  ]),
]).start();                    // start the sequence group

Nếu như một animation bị dừng đột ngột, thì tất cả các animation phía sau của nó cũng sẽ bị dừng lại. Animated.parallel có một tùy chọn là stopTogether và có thể cài đặt giá trị thành false để tắt bỏ tính năng này.

Bạn có thể thể tìm được đầy đủ các phương thức kết hợp trong Composing animations

Kết hợp các giá trị của animation

Bạn có thể kết hợp các giá trị của animation bằng cách thêm vào, nhân bản, phân chia, để tạo ra các giá trị mới của animation

Có một vài trường hợp khi một animation cần phụ thuộc vào giá trị của một animation khác để tính toán. Ví dụ như tham số phụ thuộc vào độ co giãn thì chúng ta có thể cài đặt như dưới đây:

const a = Animated.Value(1);
const b = Animated.divide(1, a);

Animated.spring(a, {
  toValue: 2,
}).start();

(Kết thúc phần 1)

Nguồn Animations


All Rights Reserved