Skip to content

NativeAnimated commandeers the animated value offset #9256

@rozele

Description

@rozele

Problem Description

When running an Animated API animation that uses an Animated.Value after calling setOffset on the value, the NativeAnimated animation does not match the experience for JS-driven animations. The root cause of this is likely because the current implementation of NativeAnimated seems to re-purpose the ValueAnimatedNode::Offset property to run the animation.

This is inconsistent with how the Animated API is supposed to work. Offsets in the Animated API are just a way to shift the animation, and the only time the offset values should change are when calling setOffset, flattenOffset, or extractOffset.

Steps To Reproduce

  1. Add an example to RNTester that calls setOffset on a value animated node, e.g.:
class Tester extends React.Component<$FlowFixMeProps, $FlowFixMeState> {
  state = {
    native: new Animated.Value(0),
    js: new Animated.Value(0),
  };

  current = 0;
  stopped = 1;
  onPress = () => {
    const animConfig =
      this.current && this.props.reverseConfig
        ? this.props.reverseConfig
        : this.props.config;
    this.current = this.current ? 0 : 1;
    const config: Object = {
      ...animConfig,
      toValue: this.current,
    };

    /* Added code for example purposes */
    this.state.native.setOffset(0.5);
    this.state.js.setOffset(0.5);
    /* End example code */

    Animated[this.props.type](this.state.native, {
      ...config,
      useNativeDriver: true,
    }).start();
    Animated[this.props.type](this.state.js, {
      ...config,
      useNativeDriver: false,
    }).start();
  };

  render() {
    return (
      <TouchableWithoutFeedback onPress={this.onPress}>
        <View>
          <View>
            <Text>Native:</Text>
          </View>
          <View style={styles.row}>
            {this.props.children(this.state.native)}
          </View>
          <View>
            <Text>JavaScript{':'}</Text>
          </View>
          <View style={styles.row}>{this.props.children(this.state.js)}</View>
        </View>
      </TouchableWithoutFeedback>
    );
  }
}
  1. Run the examples in RNTester > Native Animated Example
  2. The animation should be offset (as if it animates from 0.5 -> 1.5, rather than 0 -> 1)
  3. NativeAnimated appears to still run the animation from 0 to 1.

Expected Results

The NativeAnimated animation should match the JS-driven animation.

CLI version

npx react-native --version

Environment

npx react-native info

Target Platform Version

No response

Target Device(s)

No response

Visual Studio Version

No response

Build Configuration

No response

Snack, code example, screenshot, or link to a repository

React.Native.Playground.Win32.2021-12-08.15-06-22.mp4

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions