Animated.decay

参考示例

decay典型的使用场景是某个以组件一定的速度运行并不断减速,比如,移动(swipe或者fling)一张卡片。手指让卡片滑动并具有速度,最后卡片会因为阻力减速,并最终停止。

如果没有decay的话,那么手指停在哪里,卡片就会停在哪里。来看看如何使用:

this._animatedValue = new Animated.ValueXY();

Animated.decay(this._animatedValue, {   // coast to a stop
    velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release
    deceleration: 0.997,
})

这个效果实现出来会使什么样子的呢?幸好Brent Vatne已经做好了一个。你可以到这里看看他是如何实现的:https://github.com/brentvatne/react-native-animated-demo-tinder/blob/master/index.ios.js#L47。

    this._panResponder = PanResponder.create({
      onMoveShouldSetResponderCapture: () => true,
      onMoveShouldSetPanResponderCapture: () => true,

      onPanResponderGrant: (e, gestureState) => {
        this.state.pan.setOffset({x: this.state.pan.x._value, y: this.state.pan.y._value});
        this.state.pan.setValue({x: 0, y: 0});
      },

      onPanResponderMove: Animated.event([
        null, {dx: this.state.pan.x, dy: this.state.pan.y},
      ]),

      onPanResponderRelease: (e, {vx, vy}) => {
        this.state.pan.flattenOffset();
        var velocity;

        if (vx >= 0) {
          velocity = clamp(vx, 3, 5);
        } else if (vx < 0) {
          velocity = clamp(vx * -1, 3, 5) * -1;
        }

        if (Math.abs(this.state.pan.x._value) > SWIPE_THRESHOLD) {
          Animated.decay(this.state.pan, {
            velocity: {x: velocity, y: vy},
            deceleration: 0.98
          }).start(this._resetState)
        } else {
          Animated.spring(this.state.pan, {
            toValue: {x: 0, y: 0},
            friction: 4
          }).start()
        }
      }
    })

注意:最好是不要响上例总一样直接存取Animated.Value的值,如:_value。这是同步取值,而且会导致效率问题(不过现在Animated动画已经不支持同步取值了)。最好是添加一个事件监听器。

主要看这个方法:

onPanResponderRelease: (e, {vx, vy}) => {

On the release we the second argument is the ending gestureState, we use destructing to pop off the velocities. {vx, vy}是结束时的手势,使用这个值来计算速度:

        if (Math.abs(this.state.pan.x._value) > SWIPE_THRESHOLD) {
          Animated.decay(this.state.pan, {
            velocity: {x: velocity, y: vy},
            deceleration: 0.98
          }).start(this._resetState)
        } else {

如果用户移动卡片到某个阈值的时候(无论左右)我们会继续执行动画,知道停止。

results matching ""

    No results matching ""