+2

Cách dùng Animated trong React Native

Tổng quan

Đôi khi trong dự án react native của các bạn cũng phải cần những hiệu ứng, hoạt ảnh chuyển động nhằm mang lại cảm quan mượt mà cho người dùng, giúp cho app của chúng ta không bị nhàm chán phải không nào. Trong bài viết này mình sẽ hướng dẫn các bạn tạo ra các hiệu ứng chuyển động cơ bản dựa vào thẻ Animated được cung cấp bởi React Native mà không cần phải cài đặt thêm thư viện nào hết.

Cách dùng

1. Cơ bản

Bây giờ mình sẽ tạo một project React Native mới hoàn toàn, version react native mình dùng ở đây là 0.74.1, xoá những phần râu ria ở file App.js đi

Import: import {Animated, Easing, View} from 'react-native'

Đầu tiên tạo ra một biến để lưu giá trị của animation, giả sử ở đây là y: const y = new Animated.Value(0);

Để tránh việc re-render component có thể làm cho Animation hoạt động không như ý muốn thì nên khai báo biến y ở ngoài Component (làm cho biến animated không bị khởi tạo lại sau mỗi lần component re-render)

Muốn nó chuyển đổi thì mình sẽ đặt trong useEffect và dùng như sau:

useEffect(() => {
    Animated.timing(y, {
      toValue: 500,
      duration: 1500,
      easing: Easing.quad,
      useNativeDriver: true,
    }).start();
}, []);

Trong đó:

  • Animated.timing: Hàm tạo ra sự chuyển đổi
  • toValue: Thay đổi đến giá trị bao nhiêu
  • duration: Quá trình diễn ra trong bao lâu
  • easing: Xác định kiểu hiệu ứng, ví dụ chuyển động đều, chuyển động có gia tốc (chậm -> nhanh dần),... Sử dụng thằng Easing của react-native. Có thể dùng tool này để tạo chuyển động lúc nhanh lúc chậm https://cubic-bezier.com/ bằng Easing.bezier
  • useNativeDriver: nên dùng true

Tiếp theo, gắn giá trị animation vào trong style, lưu ý phải bọc thẻ đó bằng <Animated.View>...</Animated.View>, giả sử ở đây mình muốn nó chuyển động theo hướng nằm dọc thì mình sẽ đưa nó vào translateY:

<Animated.View
    style={{
    width: 150,
    height: 150,
    backgroundColor: 'blue',
    transform: [{ translateY: y }],
    }}
/>

Như vậy là bạn đã có thể tạo ra một hiệu ứng chuyển động chạy từ trên xuống cho thẻ view

Nếu muốn Animation dừng lại thì dùng hàm sau: Animated.timing(y).stop()

Lưu ý, có một số thuộc tính style không thể dùng được animation như width, height, margin...

2. Sequence

Sequence dùng để tạo ra trình tự biến đổi animation, ví dụ animation y ban đầu là 0 xong tăng lên 100 xong thành 500 xong xuống thành 200.

Cách dùng là có bao nhiêu trạng thái thì tạo ra bấy nhiêu Animated.timing rồi đưa tất cả vào 1 mảng bên trong Animated.sequence là được, ví dụ:

useEffect(() => {
    Animated.sequence([
      Animated.timing(y, {
        toValue: 500,
        duration: 1000,
        useNativeDriver: true,
      }),
      Animated.timing(y, {
        toValue: 100,
        duration: 1000,
        useNativeDriver: true,
      }),
      Animated.timing(y, {
        toValue: 200,
        duration: 1000,
        useNativeDriver: true,
      }),
    ]).start();
}, []);

Lưu ý, thằng .start() phải luôn được gọi ở ngoài cùng

3. Loop

Dùng để lặp đi lặp lại 1 animation nào đó Cách dùng là đặt trong một Animated.loop, ví dụ:

Animated.loop(
    Animated.timing(y, {
    toValue: 500,
    duration: 1000,
    useNativeDriver: true,
    }),
).start();

Hoặc có thể kết hợp với Sequence mà mình đã hướng dẫn ở trên:

Animated.loop(
    Animated.sequence([
    Animated.timing(y, {
      toValue: 500,
      duration: 1000,
      useNativeDriver: true,
    }),
    Animated.timing(y, {
      toValue: 100,
      duration: 1000,
      useNativeDriver: true,
    }),
    Animated.timing(y, {
      toValue: 200,
      duration: 1000,
      useNativeDriver: true,
    }),
    ]),
).start();

Trong quá trình loop Animation muốn dừng lại thì nhớ dùng hàm Animated.timing(y).stop()

4. Parallel

Khi trong màn hình của bạn có nhiều biến Animated khác nhau, và bạn muốn chạy đồng thời, lúc này nếu như bạn khai báo từng animated thì code sẽ trở nên rất dài dòng, chúng ta có thể sử dụng parallel để xử lý việc này

Giả sử mình sẽ khai báo thêm một view nữa và một biến Animated là x dùng để chuyển động ngang cho view này, thêm easing Linear để tạo chuyển động đều

Lúc này, cách sử dụng parallel như sau:

import React, { useEffect } from "react"
import { Animated, Easing, View } from "react-native"

const x = new Animated.Value(0);
const y = new Animated.Value(0);

export default App = () => {
  useEffect(() => {
    const xAnimation = Animated.loop(Animated.sequence([
      Animated.timing(x, {
        toValue: 200,
        duration: 1000,
        useNativeDriver: true,
        easing: Easing.linear
      }),
      Animated.timing(x, {
        toValue: 100,
        duration: 500,
        useNativeDriver: true,
        easing: Easing.linear
      }),
      Animated.timing(x, {
        toValue: 0,
        duration: 500,
        useNativeDriver: true,
        easing: Easing.linear
      })
    ]))
    
    const yAnimation = Animated.loop(Animated.sequence([
      Animated.timing(y, {
        toValue: 500,
        duration: 1000,
        useNativeDriver: true,
        easing: Easing.linear
      }),
      Animated.timing(y, {
        toValue: 250,
        duration: 500,
        useNativeDriver: true,
        easing: Easing.linear
      }),
      Animated.timing(y, {
        toValue: 0,
        duration: 500,
        useNativeDriver: true,
        easing: Easing.linear
      }),
    ]))

    Animated.parallel([xAnimation, yAnimation]).start()
  }, []);


  return <View style={{ flex: 1, backgroundColor: 'white' }}>
    <Animated.View
      style={{
        width: 150,
        height: 150,
        backgroundColor: 'red',
        transform: [{ translateX: x }],
      }}
    />

    <Animated.View
      style={{
        width: 150,
        height: 150,
        backgroundColor: 'blue',
        transform: [{ translateY: y }],
      }}
    />
  </View>
}

Ngoài ra Animated còn cung cấp rất nhiều các hàm và thuộc tính hữu ích khác, các bạn hãy nghiên cứu thêm nếu có thời gian nhé

Tổng kết

Bài viết trên đây mình đã hướng dẫn các bạn dùng Animated một cách cơ bản nhất, hi vọng nó sẽ giúp ích cho các bạn nhiều. Đây cũng là bài viết đầu tay của mình trên Viblo, mong rằng sẽ nhận được sự ủng hộ và góp ý từ tất cả mọi người để mình ngày càng hoàn thiện hơn, xin chân thành cảm ơn.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí