React Native 如何在新的Animated.ValueXY()上使用Animated.timing

jk9hmnmh  于 2023-04-12  发布在  React
关注(0)|答案(2)|浏览(151)

const animation = new Animated.ValueXY()我可以做

Animated.timing(animation, { toValue: 0, duration: 500})

我如何用const animation = new Animated.ValueXY()在X和Y上实现这一点?

ngynwnxp

ngynwnxp1#

与将值初始化为const animation = new Animated.ValueXY({x: 0, y: 0})的方法相同:

Animated.timing(animation, { 
     toValue: {x: 0, y: 0}, 
     duration: 500
})

所有与Animated.ValueXY相关的操作的行为都是相同的。{x: num, y: num}而不是数字。

sbtkgmzw

sbtkgmzw2#

从加布里埃尔的上述回答进一步完善:我最近还发现:

  • Animated.ValueXY而不是Animated.Value声明你想要动画的对象似乎需要使用useRef()而不是useState()。不过useState()仍然可以用Animated.Value很好地工作。
  • Animated.View style={...}中,在要设置动画的对象上使用getLayout()(沿着X+Y平移)可以使平移顺利进行。

例如,下面是代码片段(来源:this repo),使用Animated.Value为1个图标cloud-upload(取自FontAwesome glossary)制作动画:

const FloatingButton = () => {

  const [icon_1] = useState(new Animated.Value(40));
  const [pop, setPop] = useState(false);

  const popIn = () => {
    setPop(true);
    Animated.timing(icon_1, {
      toValue: 130,
      duration: 500,
      useNativeDriver: false,
    }).start();
    }

    const popOut = () => {
    setPop(false);
    Animated.timing(icon_1, {
      toValue: 40,
      duration: 500,
      useNativeDriver: false,
    }).start();
    }

  return(
    <View style={{
      flex: 1
    }}>
      <Animated.View style={[styles.circle, { bottom: icon_1}]}>
        <TouchableOpacity>
          <Icon name="cloud-upload" size={25} color="#FFFF" />
        </TouchableOpacity>
      </Animated.View>
      <TouchableOpacity
        style={styles.circle}
        onPress={() => {
          pop === false ? popIn() : popOut();
        }}
      >
        <Icon name="plus" size={25} color="#FFFF" />
      </TouchableOpacity>
    </View>
  )

}

export default FloatingButton;

const styles = StyleSheet.create({
  circle: {
     backgroundColor: '#f52d56',
     width: 60,
     height: 60,
     position: 'absolute',
     bottom: 40,
     right: 40,
     borderRadius: 50,
     justifyContent: 'center',
     alignItems: 'center',
  }
})

这里是我用Animated.ValueXY写的一个工作等价物,其中xy的初始值和最终值使用了随机值-注意:

  • 在最初定义icon_1时使用下面的useRef().current
  • Animated.View风格中getLayout()方法的使用
const FloatingButtonXY = () => {

  const initialXY = {
    x: 44,
    y: 260
  };

  const icon_1 = useRef(new Animated.ValueXY(initialXY)).current;

  const [pop, setPop] = useState(false);

  const popIn = () => {
    setPop(true);

    Animated.timing(icon_1, {
      toValue: {x: 100, y: -100},
      duration: 500,
      useNativeDriver: false,
    }).start();
    }

  const popOut = () => {
    setPop(false);

    Animated.timing(icon_1, {
      toValue: initialXY,
      duration: 500,
      useNativeDriver: false,
    }).start();
    }

return(
    <View style={{
      flex: 1,
    }}>
     <Animated.View style={[styles.circle, icon_1.getLayout()]}>
       <TouchableOpacity>
         <Icon name="cloud-upload" size={25} color="#FFFF" />
       </TouchableOpacity>
     </Animated.View>
      <TouchableOpacity
        style={styles.circle}
        onPress={() => {
          pop === false ? popIn() : popOut();
        }}
      >
        <Icon name="plus" size={25} color="#FFFF" />
      </TouchableOpacity>
    </View>
  )

}

export default FloatingButtonXY;

const styles = StyleSheet.create({
  circle: {
     backgroundColor: '#f52d56',
     width: 60,
     height: 60,
     position: 'absolute',
     bottom: 40,
     right: 40,
     borderRadius: 50,
     justifyContent: 'center',
     alignItems: 'center',
  }
})

如果你想设计的菜单是由几个图标组成的--通常情况下--那么你可以复制/粘贴Animated.timingAnimated.View部分,次数和要显示的图标一样多。
注意:在一个功能齐全的应用程序中,主屏幕的背景中有一个Map,为了使动画工作,我的FloatingActionButton组件需要封装在一个<View></View>标签中,该标签具有“容器样式”,例如here

相关问题