[React Native] Guide - Phần 2 - Animations Part 2
Bài đăng này đã không được cập nhật trong 7 năm
Animations
Phần 2
Theo dõi các giá trị linh động
Những giá trị của animation có thể theo dõi các giá trị khác. Chỉ cần cài đặt cho thuộc tính toValue
của một animation tới một giá trị thay thế của một animation khác là một số. Ví dụ một animation "Chat Heads" giống như đã từng được sử dụng bởi chương trình Messager trên Android có thể được triển khai với phương thức spring()
đính trên một giá trị animation khác, hoặc với timing()
và một duration
là 0 để ràng buộc việc theo dõi. Chúng ta có thể làm được điều này bằng các phép nội suy như ví dụ dưới đây:
Animated.spring(follower, {toValue: leader}).start();
Animated.timing(opacity, {
toValue: pan.x.interpolate({
inputRange: [0, 300],
outputRange: [1, 0],
}),
}).start();
Các giá trị leader
và follower
sẽ được triển khai bằng cách sử dụng Animated.ValueXY()
, ValueXY
được điều khiển đa phần là trên hệ tọa độ 2D ví dụ như quét hoặc kéo. Nó đơn giản là bao bọc những nội dung cơ bản của hai thể hiện Animated.Value
và một vài phương thức hỗ trợ sẽ được gọi thông qua chúng, việc tạo ra ValueXY
để có thể thay thế cho Value
trong một vài trường hợp. Nó cho phép bạn theo dõi đồng cả hai giá trị x
và y
trong ví dụ ở bên trên.
Theo dõi các thao tác tương tác
Tương tác với màn gì, giống như thực hiện các hành động panning hay scrolling, và các sự kiện khác nữa có thể mapping trực tiếp với các giá trị của animation bằng cách sử dụng Animated.event
. Đố hoàn toàn là cấu trúc map để các giá trị có thể thay đổi chính xác theo từng đối tượng của các sự kiện. Ở level cao nhất đố là một mảng cho phép mapping rất nhiều các tham số đầu vào, và đó là những mảng có chứa các đối tượng cần thiêt.
Để ví dụ cho việc này, khi làm việc với scolling theo chiều ngang, bạn có thể thực hiện bằng cách yêu cầu để map event.nativeEvent.contentOffset.x
tới scrollX
(chính là một Animated.Value
).
onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
[{ nativeEvent: {
contentOffset: {
x: scrollX
}
}
}]
)}
Khi sử dụng PanResponder
bạn có thể sử dụng những cài đặt đi theo chính xác theo vị trí x
và y
được lấy ra từ gestureState.dx
và gestureState.dy
. Chúng ta sử dụng một null
ở vị trí đầu tiên của mảng, và chúng ta chỉ để ý vào tham số thức hai để điều khiển các PanResponder
, ở đó chính là gestureState
.
onPanResponderMove={Animated.event(
[null, // ignore the native event
// extract dx and dy from gestureState
// like 'pan.x = gestureState.dx, pan.y = gestureState.dy'
{dx: pan.x, dy: pan.y}
])}
Trả lại giá trị hiện tại của animation
Bạn có thể chú ý rằng không có cách rõ ràng để đọc giá trị hiện tại của animation. Đây là bởi vì giá trị có thể chỉ được biết trong quá trình ứng dụng chạy. Nếu bạn cần để chạy JavaScript trong việc trả về giá trị hiện tại, có hai cách:
spring.stopAnimation(callback)
sẽ dừng animation và đưa vàocallback
với giá trị cuối cùng. Điều này hữu dụng khi muốn tạo ra các tương tác di chuyển.spring.addListener(callback)
sẽ đưa vàocallback
đồng bộ trong khi animation đang chạy, cung cấp giá trị gần nhất. Điều này hữu dụng để để lắng nghe khi có các trạng thái thay đổi, ví dụ như việc di chuyển một đối tượng để có một giá trị mới giống như người dùng kéo nó. Bởi vì các trạng thái có sự thay đổi lớn này có đội trễ so với các cử chỉ liên tục như panning cần chạy với tốc độ 60fps.
Animated
được thiết kế để liên kết đầy đủ để chạy animation có thể được chạy với hiệu năng cao, hoàn toàn độc lập của sự kiện lặp với JavaScript thông thường. Điều này là ảnh hưởng từ API, thế nên để giữ những hiểu biết đã có khi đây là một phần của hệ thống bất đồng bộ. Chuyển sang Animated.Value.addListener
như một cahcs để làm biệc với những cách thức để giới hạn. nhưng không nên sử dụng nó nhiều vì nó sẽ không có hiệu năng tốt trong tương lai.
Sử dụng Native driver
Animation API được thiết kế để liên kết. Bằng cách sử dụng native driver, chúng ta gửi mọi thứ về animation tới native trước khi bắt đâu animation, cho phép native code có thể tác động vào animation trên UI thread mà không cần phải thông qua các cầu nối với một một frame. Một lần Animation được bắt đầu, JS thread có thể bị khóa và không tác động được đến animation.
Sử dụng native driver để chạy nhưng animation thông thường là yêu cầu đơn giản. Chỉ cần thêm useNativeDriver: true
tới cấu hình animation khi nó bắt đầu chạy nó.
Animated.timing(this.state.animatedValue, {
toValue: 1,
duration: 500,
useNativeDriver: true, // <-- Add this
}).start();
Giá trị Animated chỉ tương ứng với một driver thế nên nếu bạn sử dụng native driver khi start một animation, cần phải chắc chắn rằng mọi animation trên giá trị đố đồng thời sẽ được sử dụng trên native driver.
Native driver đồng thời làm việc với Animated.event
. Đây là một sự hữu dụng đặc biệt để animation chạy theo scroll vị trí như là không có native driver. Animation sẽ luôn chạy một frame sau khi cử chỉ được động bộ tới React Native.
Animated.ScrollView // <-- Use the Animated ScrollView wrapper
scrollEventThrottle={1} // <-- Use 1 here to make sure no events are ever missed
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.animatedValue } } }],
{ useNativeDriver: true } // <-- Add this
)}
>
{content}
</Animated.ScrollView>
Bạn có thể xem native driver trong action vừng cách chạy RNTester app sau đố chạy Native Animated Example. Bạn có thể sẽ xem được source code để học cách làm thế nào để các ví dụ chạy.
Cảnh báo
Không phải rằng mọi thứ bạn đều có thể làm với Animated
, Nó hiện chỉ hỗ trợ bởi native driver. Giới hạn chính đó là bạn chỉ có thể chạy animate với các thuộc tính không phải dành cho layout: ví dụ như transform
và opacity
sẽ hoạt động. nhưng flexbox và thuộc tính vị trí thì sẽ không hoạt động. Khi sử dụng Animated.event
nó sẽ chỉ làm việc trực tiếp với event mà và không chạy sự kiện bubbling. Điều này có nghĩ là nó sẽ không làm việc với PanResponder
nhưng nó làm việc với ScrollView#onScroll
.
Bổ sung thêm các ví dụ
RNTester app có nhiều ví dụ cho Animation.
- AnimatedGratuitousApp
- NativeAnimationsExample
Nguồn Animations
All rights reserved