Git Product home page Git Product logo

Comments (41)

ethantran avatar ethantran commented on April 28, 2024 17

Hey guys, I managed to figure out how to animate almost every component and their props with setNativeProps. The key is to format the value correctly and I had to look at the code in https://github.com/react-native-community/react-native-svg/tree/master/lib/extract to get it right. All of the transform props had to be converted into a matrix for example. For path data, I used D3 to create paths and interpolate paths. You can see it in action at https://exp.host/@ethantran2/react-native-examples and find the messy but good enough code at https://github.com/ethantran/react-native-examples

from react-native-svg.

felixakiragreen avatar felixakiragreen commented on April 28, 2024 11

No @Druux , I'm following the React Native animated syntax. Here is an example from my app:

(I pulled out a lot of excess code that isn't related to the animation)

import React, { Component } from 'react'
import {
  View,
} from 'react-native'
import RNAnimated from 'Animated'
import AnimatedImplementation from 'AnimatedImplementation'

import Svg, {
  G,
  Path,
} from 'react-native-svg'

const Animated = {
  ...RNAnimated,
  G: AnimatedImplementation.createAnimatedComponent(G),
}


export default class Example extends Component {

  constructor(props) {
    super(props)

    this.state = {
      B1: new Animated.Value(0),
    }
  }

  componentDidMount() {
    this.runAnimation()
  }

  runAnimation() {
    Animated.stagger(50, [

      this.timing('B1'),

    ]).start()

    // I had more here but just cut them out

  }

  timing(id) {
    return Animated.sequence([
      Animated.timing(
        this.state[id],
        { toValue: 1, duration: 150 }
      ),
      Animated.timing(
        this.state[id],
        { toValue: 0, duration: 150 }
      )
    ])
  }

  interp(id, value) {
    return this.state[id].interpolate({
      inputRange: [0, 1],
      outputRange: value,
    })
  }

  render() {

    return (
      <Svg
        height={191}
        width={259}
      >
        <Animated.G
          originX={20}
          y={this.interp('B1', [0, -12])}
          x={this.interp('B1', [0, 2])}
          scaleX={this.interp('B1', [1, .85])}
        >
          <Path d='M36.9 23.6c0-4.07-1.32-7.34-4-9.8-2.7-2.5-6.24-3.75-10.6-3.75H1.74v57.9l18.58-.02c6.3 0 11.3-1.5 15-4.48 3.67-3 5.5-7.06 5.5-12.15 0-4.15-1.12-7.43-3.38-9.84l-.42-.42c-2.27-2.15-5.55-3.55-9.84-4.2 3.27-1.34 5.72-3.13 7.36-5.34 1.6-2.22 2.4-4.85 2.4-7.9zm-21.68 8.7v-11h2.52c1.85 0 3.24.43 4.16 1.28.9.84 1.37 2.1 1.37 3.77 0 1.86-.58 3.3-1.73 4.37-1.2 1.06-2.8 1.6-4.82 1.6h-1.5zm0 10.75h4.34c2.14 0 3.92.6 5.36 1.85 1.43 1.22 2.15 2.85 2.15 4.9 0 2-.7 3.64-2.1 4.9-1.43 1.25-3.23 1.87-5.4 1.87H15.2V43.05z'/>
        </Animated.G>

      </Svg>

    )
  }
}

Disclaimer: I'm sure this isn't the best way to do this. But it worked for me.
I set up my own interpolate function so that I could pass the two values into the render. I also used IDs because I had 20 different animations going.

Good luck. Don't know if this will help you.

from react-native-svg.

joshuapinter avatar joshuapinter commented on April 28, 2024 10

Hey All, I just wanted to follow up from my comment before.

I did a bit more tinkering and found a very workable solution using addListener and setNativeProps. A little messy but works none-the-less and is quite performant.

Here's a simplified version of the solution:

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() {
  return(
    <Svg height="400" width="400">
      <AnimatedCircle ref={ ref => this._myCircle = ref } cx="250" cy="250" r="50" fill="black" />
    </Svg>
  )
}

And the resulting animation:

circle animation with setnativeprops

And this is being rendered on a very complex component where using setState isn't fluid at all.

from react-native-svg.

TheDirtyCalvinist avatar TheDirtyCalvinist commented on April 28, 2024 9

By setting a listener on the animation that calculates a new path and calls this.pathComponent.setNativeProps({ d });, some semblance of an animation can be had. The Path component does not need to be wrapped in Animated.

from react-native-svg.

felixakiragreen avatar felixakiragreen commented on April 28, 2024 2

Hey, no worries. I got it working by doing this:

import AnimatedImplementation from 'AnimatedImplementation'

import Svg, {
  G,
  Path,
} from 'react-native-svg'

const A = {
  Svg: AnimatedImplementation.createAnimatedComponent(Svg),
  G: AnimatedImplementation.createAnimatedComponent(G),
  Path: AnimatedImplementation.createAnimatedComponent(Path),
}

from react-native-svg.

matc4 avatar matc4 commented on April 28, 2024 2

Hello @DUBERT,

What is AnimatedImplementation?

Thanks!

from react-native-svg.

keksipurkki avatar keksipurkki commented on April 28, 2024 2

@edo1493, I figured out how to make animations work. The process of generating the intermediate paths is called tweening and there is actually a library that lets you do it given two paths: art (https://www.npmjs.com/package/art).

I adapted the code from this demo: https://medium.com/the-react-native-log/animated-charts-in-react-native-using-d3-and-art-21cd9ccf6c58

See: http://ix.io/tgW/javascript

from react-native-svg.

magicismight avatar magicismight commented on April 28, 2024

Animation is in my TODO list.

from react-native-svg.

felixakiragreen avatar felixakiragreen commented on April 28, 2024

Perhaps I could help with it?

from react-native-svg.

felixakiragreen avatar felixakiragreen commented on April 28, 2024

It's React-Native's built in Animation library

from react-native-svg.

beeirl avatar beeirl commented on April 28, 2024

@DUBERT Is there any possibility to provide a code example of your solution? Is your approach quite equal to the Svg's <animate /> synatx?

from react-native-svg.

beeirl avatar beeirl commented on April 28, 2024

Alright - that were my thoughts how you solved this as well @DUBERT.
The issue I am currently facing is that I can't assign an Animated.Value() to the svg attribute strokeDasharray because it needs an array. And it isn't possible to convert an Animated.Value() to an array with this syntax: strokeDasharray={[this.state.strokeDasharray]}. (Tried out some more workarounds for that specific case, but it seems like there is no one).

I should probably go ahead with requestAnimationFrame()

from react-native-svg.

felixakiragreen avatar felixakiragreen commented on April 28, 2024

can you post the values that you're trying to animate?

from react-native-svg.

FlaviooLima avatar FlaviooLima commented on April 28, 2024

@DUBERT how did you make it to work?
I can use your theory with react native ART but not with react-native-svg.
I use the same code and same components and the only thing i change was the components from react native ART and react-native-svg, and in ART works but no success in svg.

from react-native-svg.

felixakiragreen avatar felixakiragreen commented on April 28, 2024

@flaviotobi do you have your source code on a repo somewhere that I can take a look?
If not, I will consider posting a working example of SVG animation because it's gotten a lot of questions.

from react-native-svg.

FlaviooLima avatar FlaviooLima commented on April 28, 2024

Thanks for the reply =D

This code was tested in iOS, using :
react-native: 0.31.0
react-native-svg: 4.1.5
and
react-native: 0.33.0
react-native-svg: 4.3.1

Animation working with ART: §
https://rnplay.org/apps/EudZ0g

Animation not working with SVG:
https://rnplay.org/apps/95DeZA

from react-native-svg.

julesmoretti avatar julesmoretti commented on April 28, 2024

Would love also some help here. I am trying to animate a path to create an animated pie chart... But right now I am not able to get the animated to work with it, unless I use a separate setInterval and forceUpdate() which I am sure = bad!

So here is what I have right now and hopefully someone can help me a tad with this :) thank you.

import React from 'react';

import {
	View,
	StyleSheet,
	Animated,
	Easing,
} from 'react-native';

import Svg,{
	G,
	RadialGradient,
	Path
} from 'react-native-svg';

// create custom animatable component for paths
let AnimatedPath = Animated.createAnimatedComponent(Path);

const SCREEN_SIZE = 200;

export class AnimatedPie extends React.Component {

	constructor(props, context) {
		super(props, context);

		// set state with animatable value
		this.state = {
			piePercentage: new Animated.Value(100),
		};
	}

	componentDidMount() {

		// start animation on mounting going from 100 to 0
		// full pie chart down to empty pie
		Animated.timing(
			this.state.piePercentage,
			{
				toValue: 0,
				easing: Easing.linear,
				duration: 10000,
			}
		).start();
	}

	polarToCartesian(centerX, centerY, radius, angleInDegrees) {
		var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0;

		return {
			x: centerX + (radius * Math.cos(angleInRadians)),
			y: centerY + (radius * Math.sin(angleInRadians))
		};
	}

	// function that spits out a pie chart path shape using a range to determine the pie volume
	progress( timeRange, time ) {

		let center = SCREEN_SIZE / 2;

		if ( timeRange && time ) {

			let x = center;
			let y = center;
			let radius = center;
			let startAngle = 0;
			let endAngle = 360 / timeRange * time

			let start = this.polarToCartesian(x, y, radius, startAngle);
			let end = this.polarToCartesian(x, y, radius, endAngle);

			let largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";

			let d = [
					"M", radius, 0,
					"L", radius, radius,
					"L", end.x, end.y,
					"M", end.x, end.y,
					"A", radius, radius, 0, largeArcFlag, 0, start.x, start.y,
					"Z"
			].join(" ");
			return(d);
		} else {
			return("M0 0");
		}
	}

	render() {
		return (
			<Svg
				width={SCREEN_SIZE}
				height={SCREEN_SIZE}>

				<AnimatedPath
					d={this.progress( 100, this.state.piePercentage)} // this is not working as is...
					fill="#fe5d4d"
					stroke="none"
				/>

			</Svg>
		)
	}
}

from react-native-svg.

joshuapinter avatar joshuapinter commented on April 28, 2024

Were you ever able to get an AnimatedPath working? I'm currently trying to do something similar, but even easier with just changing the radius of a circle, without using styles and scale.

// var AnimatedCircle = Animated.createAnimatedComponent(Circle); <-- Done before.

<AnimatedCircle cx="250" cy="250" r={this.state.circleRadius} fill="black" />

With the following animation on mount:

// this.state.circleRadius = 50 <-- Starting value

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

And getting the following error:

screenshot 2017-03-03 11 00 44

from react-native-svg.

ClinicalCharles avatar ClinicalCharles commented on April 28, 2024

Some SVG elements are animatable but others aren't. SVG is animatable and I think G may be as well but Path isn't.
I performed a basic fade animation of a path by making the enclosing SVG element animatable and operating on it like this:

import Svg,{
    Line,
    Path,
    Rect,
    Text as SVGText
} from 'react-native-svg';

import RNAnimated from 'Animated'
import AnimatedImplementation from 'AnimatedImplementation'

const Animated = {
  ...RNAnimated,
  Svg: AnimatedImplementation.createAnimatedComponent(Svg),
}

<Animated.Svg height={Height} width={Width} 
           style={{position: 'absolute', opacity: this.state.fadeAnim}}>  
          <Path
            d={linePath}
            stroke='black'
            fill="none"
            strokeWidth={2}
          />
        </Animated.Svg>

If you want to do anything more complex then I recommend ART.
There are some really useful articles available at http://browniefed.com/

from react-native-svg.

TheDirtyCalvinist avatar TheDirtyCalvinist commented on April 28, 2024

It appears that Path is animatable via the setNativeProps function.

from react-native-svg.

keksipurkki avatar keksipurkki commented on April 28, 2024

@TheDirtyCalvinist Could you elaborate, please?

from react-native-svg.

edo1493 avatar edo1493 commented on April 28, 2024

Hey @TheDirtyCalvinist, how would you interpolate a d path?

from react-native-svg.

TheDirtyCalvinist avatar TheDirtyCalvinist commented on April 28, 2024

It would depend on the animation you are trying to achieve.

from react-native-svg.

edo1493 avatar edo1493 commented on April 28, 2024

@TheDirtyCalvinist In my case, I have a piechart and when I highlight a slice, the radius gets bigger, so I'd like to animate the path and make it grow smoothly.

At this point, I am not sure, if the best approach is to animate the path or even the radius.

from react-native-svg.

edo1493 avatar edo1493 commented on April 28, 2024

@keksipurkki I don't use ART, cause it doesn't support click events. ;)

from react-native-svg.

keksipurkki avatar keksipurkki commented on April 28, 2024

@edo1493, Yeah, but take a look at the code, it uses react native SVG for rendering and ART for tweening. I have implemented a clickable SVG pie chart ;-P

AFAIK, the tweening functionality could be incorporated into react native svg. It's pure computation with no dependencies on a particular DOM implementation.

from react-native-svg.

edo1493 avatar edo1493 commented on April 28, 2024

@keksipurkki Yes, I know that blog post really well. I just re-adapted the whole thing without ART. I am using the onClick events to highlight the slice and make it bigger, it would be nice to have an Animation when the slice gets bigger.

from react-native-svg.

keksipurkki avatar keksipurkki commented on April 28, 2024

@edo1493 See my edited comment above.

from react-native-svg.

edo1493 avatar edo1493 commented on April 28, 2024

I tried the tweening too in the past couple of months, but it was breaking things for me. Adding an eventListener as @TheDirtyCalvinist was mentioning (also here: http://stackoverflow.com/questions/39094349/how-to-make-svg-animation-with-animated-in-react-native) seemed a smoother solution.

However, I am not sure how to interpolate my next path, which I am getting from componentWillReceiveProps.

from react-native-svg.

keksipurkki avatar keksipurkki commented on April 28, 2024

@edo1493 Yup. For me the problem is currently that orientation change screws up the chart.

from react-native-svg.

toearth avatar toearth commented on April 28, 2024

I try keksipurkki's solution, it works well.

from react-native-svg.

edo1493 avatar edo1493 commented on April 28, 2024

I am trying to animate a slice of a piechart, in this way:

class AnimatedSlice extends React.Component {

  constructor(props) {
    super(props);

    this.state = { path: new Animated.Value(this.props.d) };

    this.state.path.addListener( (path) => {
      this.mySlice.setNativeProps({ d: path.value.toString() });
    });

  }

  componentWillReceiveProps(nextProps) {
    let value = new Animated.Value(nextProps.d);
    setTimeout( () => {
      Animated.spring( this.state.path, { toValue: value, friction: 3 } ).start();
    });
  }

  render() {
    let path = this.props.d;
    return (
      <AnimatedPath
        ref={ ref => this.mySlice = ref }
        fill={this.props.color}
        fillOpacity={1}
        d={path}
        onPress={() => this.props.onPress()}/>
    )
  }
}

module.exports = AnimatedSlice;

Do you guys have any tips? Nothing is moving here. I just want a smooth animation when a new path comes in. I have chosen spring with some friction, just to give it a go, it's not the animation that I want. If I can animate it in any way first, it would be great.

@TheDirtyCalvinist @joshuapinter

from react-native-svg.

FMCorz avatar FMCorz commented on April 28, 2024

It'd be nice if the information found in this issue was transformed into documentation. I have not found any other documentation regarding how to animate SVG parts.

In someone is looking at interpolating colours, I've managed to make it work. Here is a snippet which is has to be mixed with the examples found above:

import extractProps from 'react-native-svg/lib/extract/extractProps';

...

const colour = new Animated.Value(0);
colour.addListener(v => {

    const c = colour.interpolate({
      inputRange: [0, 1],
      outputRange: ['black', 'red']
    });

    // Make sure that the ref was acquired.
    if (this.myRef) {

      // Convert the interpolation to a value, and assign to prop name.
      const props = {
        fill: c.__getValue()
      }

      // Conver the properties to native properties.
      const nativeProps = extractProps(props, this.myRef);

      // Finally send the properties to the object.
      this.myRef.setNativeProps(nativeProps);
    }
});

As @ethantran mentioned, some props need to be converted to their native equivalents. However, a colour interpolation first needs to be converted to a value or the extractProps chain will not know what to do with it. So the trick in the above example is to use __getValue(). Perhaps __getNativeValue() is better, but the former worked for me.

from react-native-svg.

ricklove avatar ricklove commented on April 28, 2024

@ethantran Well done! Very Nice! 👏👏👏

I didn't even know using D3 was doable. Will be using your examples for sure. 🤜🤛

from react-native-svg.

ma-pe avatar ma-pe commented on April 28, 2024

@FMCorz Thanks for the inspiration. This can be even easier if you just want to set the fill-color:

import extractBrush from 'react-native-svg/lib/extract/extractBrush';
...
const colour = new Animated.Value(0);
colour.addListener(v => {
     const c = color.interpolate({
        inputRange: [0, 1],
        outputRange: ['black', 'red'],
      });

      // Make sure that the ref was acquired.
      if (this.maskRectRef) {
        this.maskRectRef.setNativeProps({ fill: extractBrush(c.__getValue()) });
      }
});

and rendering:

    const c = color.interpolate({
      inputRange: [0, 1],
      outputRange: ['black', 'red'],
    });
    return (
          <Rect
            ref={ref => (this.maskRectRef = ref)}
            fill={c.__getValue()}
            ...
          />
     );
...

from react-native-svg.

Yaweii avatar Yaweii commented on April 28, 2024

@ethantran Hi I am new to react native and I'm trying to build This Example in react native. Basically it's a line chart with real-time data. Would you mind sharing some thoughts? Much appreciated!

from react-native-svg.

Yaweii avatar Yaweii commented on April 28, 2024

@DUBERT Hi I am new to react native and I'm trying to buildThis Example in react native. Basically it's a line chart with real-time data. Would you mind sharing some thoughts? Much appreciated!

from react-native-svg.

rantoinne avatar rantoinne commented on April 28, 2024

@DUBERT how do we animate a pie chart so that each pie of the chart renders in a circular way.
I have been on this since a lot of days and have tried dozens of ideas but unable to achieve a perfect animation.
Can you help me with this.??

from react-native-svg.

xiawaner avatar xiawaner commented on April 28, 2024

@DUBERT我们如何设置饼图的动画,以便图表的每个饼以圆形方式呈现。
很多天以来我一直在这方面,并尝试过几十个想法,但无法实现完美的动画效果。
你能帮帮我吗?

Study this library and try it out

https://github.com/JesperLekland/react-native-svg-charts
https://github.com/JesperLekland/react-native-svg-charts-examples

from react-native-svg.

rantoinne avatar rantoinne commented on April 28, 2024

Have tried these too. Actually I also need the pies to be touchable. Using it caused a lot of bugs while integrating touchables though the docs support that the library has it.

from react-native-svg.

rantoinne avatar rantoinne commented on April 28, 2024

Wrapping the path component in a new class will help us achieve functionality for adding a delay for successive mappings.. I did so to animate my pie chart such that each of its pie are visible one after the other after a delay. Thanks for all the help I got from here. :-)

from react-native-svg.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.