Skip to content

Commit

Permalink
Fix connection of AnimatedNodes and creation of redundant AnimatedNodes
Browse files Browse the repository at this point in the history
When using one AnimatedValue to interpolate several properties in one
View, it caused several redundant AnimatedNodes to be created for the
same AnimatedProps.

Additionally, the connections to the AnimatedProps were made before the
native node for the AnimatedProps was created, causing them not to work.
This queues the connection creation until all the nodes are created.

A cleaner solution might be to split the connecting part out from
__makeNative into a separate method, and call that in
__startNativeAnimation, but at least this works.

Test App.js:
```jsx
import React, { Component } from 'react';
import { StyleSheet, View, Dimensions, Animated } from 'react-native';
import { Svg, Rect, Path } from 'react-native-svg';

const { width, height } = Dimensions.get('window');
const AnimatedRect = Animated.createAnimatedComponent(Rect);
const AnimatedPath = Animated.createAnimatedComponent(Path);

function getInitialState() {
  const anim = new Animated.Value(0);
  const fillOpacity = anim.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1],
  });
  const offset = anim.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 10],
  });
  const strokeOpacity = anim.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1],
    extrapolateRight: 'clamp',
  });
  const path = anim.interpolate({
    inputRange: [0, 1],
    outputRange: ['M20,20L20,80L80,80L80,20Z', 'M40,40L33,60L60,60L65,40Z'],
  });
  const fill = anim.interpolate({
    inputRange: [0, 1],
    outputRange: ['rgba(255, 0, 0, 0.5)', 'rgba(0, 255, 0, 0.99)'],
  });
  const oneToFivePx = anim.interpolate({
    inputRange: [0, 1],
    outputRange: ['1px', '5px'],
  });
  return { anim, fillOpacity, offset, strokeOpacity, path, fill, oneToFivePx };
}

export default class App extends Component {
  state = getInitialState();

  componentDidMount() {
    const { anim } = this.state;
    Animated.timing(anim, {
      toValue: 1,
      duration: 10000,
      useNativeDriver: true,
    }).start();
  }

  render() {
    const { fillOpacity, offset, strokeOpacity, path, fill, oneToFivePx } = this.state;
    return (
      <View style={styles.container}>
        <Svg width={width} height={height} viewBox="0 0 100 100">
          <AnimatedRect
            x="5"
            y="5"
            width="90"
            height="90"
            stroke="blue"
            fill={fill}
            strokeDasharray="1 1"
            strokeWidth={oneToFivePx}
            strokeDashoffset={offset}
            strokeOpacity={strokeOpacity}
            fillOpacity={fillOpacity}
          />
          <AnimatedPath
            d={path}
            stroke="blue"
          />
        </Svg>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: '#ecf0f1',
  },
});
```
  • Loading branch information
msand committed Feb 27, 2019
1 parent 0dfd233 commit c7182cd
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 1 deletion.
1 change: 1 addition & 0 deletions Libraries/Animated/src/animations/Animation.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class Animation {
}
__startNativeAnimation(animatedValue: AnimatedValue): void {
animatedValue.__makeNative();
animatedValue.__connectAnimatedNodes();
this.__nativeId = NativeAnimatedHelper.generateNewAnimationId();
NativeAnimatedHelper.API.startAnimatingNode(
this.__nativeId,
Expand Down
8 changes: 7 additions & 1 deletion Libraries/Animated/src/nodes/AnimatedNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,18 @@ class AnimatedNode {

/* Methods and props used by native Animated impl */
__isNative: boolean;
__isConnected: boolean;
__nativeTag: ?number;
__makeNative() {
if (!this.__isNative) {
throw new Error('This node cannot be made a "native" animated node');
}
}
__connectAnimatedNodes() {
if (!this.__isNative) {
throw new Error('This node cannot be connected natively');
}
}
__getNativeTag(): ?number {
NativeAnimatedHelper.assertNativeAnimatedModule();
invariant(
Expand All @@ -49,11 +55,11 @@ class AnimatedNode {
);
if (this.__nativeTag == null) {
const nativeTag: ?number = NativeAnimatedHelper.generateNewNodeTag();
this.__nativeTag = nativeTag;
NativeAnimatedHelper.API.createAnimatedNode(
nativeTag,
this.__getNativeConfig(),
);
this.__nativeTag = nativeTag;
}
return this.__nativeTag;
}
Expand Down
9 changes: 9 additions & 0 deletions Libraries/Animated/src/nodes/AnimatedWithChildren.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ class AnimatedWithChildren extends AnimatedNode {
this.__isNative = true;
for (const child of this._children) {
child.__makeNative();
}
}
}

__connectAnimatedNodes() {
if (!this.__isConnected) {
this.__isConnected = true;
for (const child of this._children) {
child.__connectAnimatedNodes();
NativeAnimatedHelper.API.connectAnimatedNodes(
this.__getNativeTag(),
child.__getNativeTag(),
Expand Down

0 comments on commit c7182cd

Please sign in to comment.