reactnative 动画实现

先看一个示例

class Playground extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      bounceValue: new Animated.Value(0),
    };
  }
  render() {
    return (
      <Animated.Image                         // Base: Image, Text, View
        source={{uri: 'http://i.imgur.com/XMKOH81.jpg'}}
        style={{
          flex: 1,
          transform: [                        // `transform` is an ordered array
            {scale: this.state.bounceValue},  // Map `bounceValue` to `scale`
          ]
        }}
      />
    );
  }
  componentDidMount() {
    this.state.bounceValue.setValue(1.5);     // Start large
    Animated.spring(                          // Base: spring, decay, timing
      this.state.bounceValue,                 // Animate `bounceValue`
      {
        toValue: 0.8,                         // Animate to smaller size
        friction: 1,                          // Bouncier spring
      }
    ).start();                                // Start the animation
  }
}

动画是从 Animated.spring开始的

找到对应实现

var spring = function(
  value: AnimatedValue | AnimatedValueXY,
  config: SpringAnimationConfig,
): CompositeAnimation {
  return maybeVectorAnim(value, config, spring) || {
    start: function(callback?: ?EndCallback): void {
      callback = _combineCallbacks(callback, config);
      var singleValue: any = value;
      var singleConfig: any = config;
      singleValue.stopTracking();
      if (config.toValue instanceof Animated) {
        singleValue.track(new AnimatedTracking(
          singleValue,
          config.toValue,
          SpringAnimation,
          singleConfig,
          callback
        ));
      } else {
        singleValue.animate(new SpringAnimation(singleConfig), callback);
      }
    },

    stop: function(): void {
      value.stopAnimation();
    },
  };
};

看来目标值存在singleValue,然后结束值和动画实现放在singleConfig

这里start函数都直接有的
最重要的是singleValue.animate(new SpringAnimation(singleConfig), callback);

singlevalue是一个Animated.Value 类型。调用这里面的animate方法。然后传入的类型是SpringAnimation。

Animated.Value

下面研究Animated.Value类型(这个类型我找不到) 但是从函数定义上来来说 是AnimatedValue类型

下面是value 的实现

  animate(animation: Animation, callback: ?EndCallback): void {
    var handle = null;
    if (animation.__isInteraction) {
      handle = InteractionManager.createInteractionHandle();
    }
    var previousAnimation = this._animation;
    this._animation && this._animation.stop();
    this._animation = animation;
    animation.start(
      this._value,
      (value) => {
        // Natively driven animations will never call into that callback, therefore we can always
        // pass flush = true to allow the updated value to propagate to native with setNativeProps
        this._updateValue(value, true /* flush */);
      },
      (result) => {
        this._animation = null;
        if (handle !== null) {
          InteractionManager.clearInteractionHandle(handle);
        }
        callback && callback(result);
      },
      previousAnimation,
      this
    );
  }

看来是调用
SpringAnimation的start方法给了一个初始值 然后穿了两个函数。
主要是的是把_updateValue 也传了进去。

先把_updateValue放在这里。

 _updateValue(value: number, flush: bool): void {
    this._value = value;
    if (flush) {
      _flush(this);
    }
    for (var key in this._listeners) {
      this._listeners[key]({value: this.__getValue()});
    }
  }

class SpringAnimation extends Animation

SpringAnimation 在构造的时候就知道动画结束值和动画的持续时间

 constructor(
    config: SpringAnimationConfigSingle,
  ) {
    super();

    this._overshootClamping = withDefault(config.overshootClamping, false);
    this._restDisplacementThreshold = withDefault(config.restDisplacementThreshold, 0.001);
    this._restSpeedThreshold = withDefault(config.restSpeedThreshold, 0.001);
    this._initialVelocity = config.velocity;
    this._lastVelocity = withDefault(config.velocity, 0);
    this._toValue = config.toValue;
    this._useNativeDriver = shouldUseNativeDriver(config);
    this.__isInteraction = config.isInteraction !== undefined ? config.isInteraction : true;

结束值在this._toValue里面

start函数

  start(
    fromValue: number,
    onUpdate: (value: number) => void,
    onEnd: ?EndCallback,
    previousAnimation: ?Animation,
    animatedValue: AnimatedValue
  ): void {
    this.__active = true;
    this._startPosition = fromValue;
    this._lastPosition = this._startPosition;

    this._onUpdate = onUpdate;
    this.__onEnd = onEnd;
    this._lastTime = Date.now();

    if (previousAnimation instanceof SpringAnimation) {
      var internalState = previousAnimation.getInternalState();
      this._lastPosition = internalState.lastPosition;
      this._lastVelocity = internalState.lastVelocity;
      this._lastTime = internalState.lastTime;
    }
    if (this._initialVelocity !== undefined &&
        this._initialVelocity !== null) {
      this._lastVelocity = this._initialVelocity;
    }
    if (this._useNativeDriver) {
      this.__startNativeAnimation(animatedValue);
    } else {
      this.onUpdate();
    }
  }

start里面有个重点

 if (this._useNativeDriver) {
      this.__startNativeAnimation(animatedValue);
    } else {
      this.onUpdate();
      }

非native

这里会区分是本地动画还是自己的动画。
先分析onUpdate
opUpdate会计算出当前时间动画的值
然后调用this._onUpdate
这个就是AnimatedValue传进来的回调函数。执行的是AnimatedValue的 this._updateValue(value, true /* flush */);
这个函数会大flush标记 和 通知监听者 todo

看来SpringAnimation只是用于计算动画的当前的值。并没有涉及到原理性的东西。

native

下面看一下native的实现
__startNativeAnimation

__startNativeAnimation(animatedValue: AnimatedValue): void {
    animatedValue.__makeNative();
    this.__nativeId = NativeAnimatedHelper.generateNewAnimationId();
    NativeAnimatedAPI.startAnimatingNode(
      this.__nativeId,
      animatedValue.__getNativeTag(),
      this.__getNativeAnimationConfig(),
      this.__debouncedOnEnd.bind(this)
    );
  }

现在要去看NativeAnimatedHelper.js

下面就是要做分平台处理了
ios RCTNativeAnimatedModule.m
Android NativeAnimatedModule.java

RCTNativeAnimatedModule.m

这个类对外提供接口
RCT_EXPORT_METHOD(startAnimatingNode:(nonnull NSNumber *)animationId
nodeTag:(nonnull NSNumber *)nodeTag
config:(NSDictionary

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值