CoderLim
CoderLim

Reputation: 1232

How to make svg animation with Animated in react-native

ReactNative:

<ScrollView style={styles.container}>
    <Svg
      height="100"
      width="100">
        <Circle
          cx="50"
          cy="50"
          r="50"
          stroke="blue"
          strokeWidth="2.5"
          fill="green"/>
      </Svg>
</ScrollView>

I want to make Circle scale with Animated.Value. I have tried this :

    let AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
    let AnimatedCircle = Animated.createAnimatedComponent(Circle);

    <ScrollView style={styles.container}>
            <Svg
              height="100"
              width="100">
                <AnimatedCircle
                  cx="50"
                  cy="50"
                  r={this.state.animator}
                  stroke="blue"
                  strokeWidth="2.5"
                  fill="green"/>
              </Svg>
        </ScrollView>

Then flash back with no error.

How can I do?


update 2016.8.24

I found a new way instead of requestAnimationFrame :

constructor:

this.state = {
      animator: new Animated.Value(0),
      radius: 1,
    };

    this.state.animator.addListener((p) => {
      this.setState({
        radius: p.value,
      });
    });

render:

<Circle
    cx="50"
    cy="50"
    r={this.state.radius}
    stroke="blue"
    strokeWidth="2.5"
    fill="green"/>

But here the guides gives advice using it sparingly since it might have performance implications in the future.

so what's the best way ?

Upvotes: 16

Views: 36565

Answers (3)

Jeremy Patrick Pacabis
Jeremy Patrick Pacabis

Reputation: 687

i have created a simple svg animations library based on a project by another person, for now, only Paths can be animated but more shapes and animations will be added in the future

https://www.npmjs.com/package/react-native-svg-animations

Upvotes: 2

Joshua Pinter
Joshua Pinter

Reputation: 47471

Use setNativeProps for Much Better Performance.

I did some more tinkering and found a more performant method that makes use of addListener and setNativeProps.

Constructor

constructor(props) {
  super(props);

  this.state = { circleRadius: new Animated.Value(50) };

  this.state.circleRadius.addListener( (circleRadius) => {
    this._myCircle.setNativeProps({ r: circleRadius.value.toString() });
  });

  setTimeout( () => {
    Animated.spring( this.state.circleRadius, { toValue: 100, friction: 3 } ).start();
  }, 2000)
}

Render

render() {
  return(
    <Svg height="400" width="400">
      <AnimatedCircle ref={ ref => this._myCircle = ref } cx="250" cy="250" r="50" fill="black" />
    </Svg>
  )
}

Result

And this is what the animation looks like when the 2 second (2000 millisecond) timeout triggers.

circle animation with setnativeprops

So, the main thing you needed to change was using setNativeProps instead of using setState in your listener. This makes a native call and bypasses re-calculating the entire component, which in my case was very complex and slow to do.

Thanks for leading me towards the listener approach!

Upvotes: 23

CoderLim
CoderLim

Reputation: 1232

No better answers, and I implemented by adding listener to Animated.Value variable, you can get more info from my question description.

Upvotes: 0

Related Questions