背景
学校留了一个作业,要用 React Native 做个游戏。我做的游戏涉及物体下落的效果,今天来尝试一下使用 React Native 的 Animated API 来实现这个效果。
实现
代码
比较简单,这次直接上代码吧:
import { useRef, useEffect } from 'react';
import { Animated, Dimensions } from 'react-native';
const WINDOW_WIDTH = Dimensions.get('window').width;
const WINDOW_HEIGHT = Dimensions.get('window').height;
const BOX_SIZE = WINDOW_WIDTH / 5;
const BOX_INIT_X = WINDOW_WIDTH/2 - BOX_SIZE/2;
const BOX_INIT_Y = WINDOW_WIDTH/2;
const BOX_FINAL_Y = WINDOW_HEIGHT - BOX_SIZE
export default function App() {
const positionY = useRef(new Animated.Value(BOX_INIT_Y)).current
useEffect(() => {
// 使用 Animated.timing 设置动画
Animated.timing(
positionY,
{
toValue: BOX_FINAL_Y, // 在动画过程中把 positionY 变量改变到这个值
duration: 3000,
useNativeDriver: false // 注意这里,true 的性能会更好,但这里只能选 false,除非换一种方式使用 positionY
}
).start();
}, [])
const boxStyle = {
position: 'absolute',
top: positionY, // positionY 用来指定盒子的 y 轴位置
left: BOX_INIT_X,
width: BOX_SIZE,
height: BOX_SIZE,
backgroundColor: 'red'
}
return <Animated.View style={boxStyle} />
}
需要注意的几点
useNativeDriver
这个选项写成了false
。如果选true
的话会报错,因为top
这个样式不支持 native driver。如果一定要用useNativeDriver: true
(性能会更好),可以考虑使用transform
,参考链接- 由于
positionY
是一个Animated.Value
类型,使用的时候只能直接用,比如top: positionY
,不能在其基础上进行运算,比如写成top: positionY + 100
就会报错; - 上面用的是
useRef
,但用useState
来定义positionY
也完全没问题。但即便positionY
是个 state,在动画过程中也不会触发组件函数重新执行,因为setPositionY
并没有被调用,其值的改变是通过positionY.setValue()
实现的;
效果
效果如下: