Comments (41)
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.
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.
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:
And this is being rendered on a very complex component where using setState
isn't fluid at all.
from react-native-svg.
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.
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.
Hello @DUBERT,
What is AnimatedImplementation?
Thanks!
from react-native-svg.
@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.
Animation is in my TODO list.
from react-native-svg.
Perhaps I could help with it?
from react-native-svg.
It's React-Native's built in Animation library
from react-native-svg.
@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.
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.
can you post the values that you're trying to animate?
from react-native-svg.
@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.
@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.
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.
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.
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:
from react-native-svg.
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.
It appears that Path
is animatable via the setNativeProps
function.
from react-native-svg.
@TheDirtyCalvinist Could you elaborate, please?
from react-native-svg.
Hey @TheDirtyCalvinist, how would you interpolate a d path?
from react-native-svg.
It would depend on the animation you are trying to achieve.
from react-native-svg.
@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.
@keksipurkki I don't use ART, cause it doesn't support click events. ;)
from react-native-svg.
@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.
@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.
@edo1493 See my edited comment above.
from react-native-svg.
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.
@edo1493 Yup. For me the problem is currently that orientation change screws up the chart.
from react-native-svg.
I try keksipurkki's solution, it works well.
from react-native-svg.
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.
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.
@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.
@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.
@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.
@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.
@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.
@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.
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.
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)
- Usage of std::stof crashes on Windows when using some non-English languages/locales (i.e. German / de) HOT 2
- `translateY` isn't working in react-native-web
- `Module parse failed` error when building for Storybook for web
- React Native Svg Linear Gradient Not loading when redirecting to bottom navigation tab HOT 1
- [Error: Expected > (0:110). If this is valid SVG, it's probably a bug. Please raise an issue HOT 3
- toDataURL only works the second time it is executed in old Arch HOT 1
- [Invariant Violation: requireNativeComponent: "RNSVGSvgView" was not found in the UIManager. HOT 7
- onPress in Path don't works on iOS, on android works
- The onPress method in the Path component works on android but not on ios.
- Svg Image pointerEvents="none" not working on Android
- Invalid `RNSVG.podspec` file: undefined method `visionos' for #<Pod::Specification name="RNSVG">. HOT 11
- Invariant Violation: requireNativeComponent: "RNSVGPath" was not found in the UIManager. HOT 2
- Fatal Exception: java.lang.Error Invalid number formating character 'N'
- SvgUri can not load some of the svgs in both android and ios
- Animating the strokeDashArray prop of an animated Path crashes running on the Android Simulator
- <Text /> with PanResponder only works if you click exactly on the letters
- Failed parsing SvgCssUri for first time, after reopening app it appears
- Xlinkhref only work on web does not work on ios and android (the color did not get inherited ) HOT 2
- React native web + vitest issue - Cannot use import statement outside a module HOT 4
- fetchText method error : TypeError: Cannot read property 'prototype' of undefined when trying to call svg from uri
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-native-svg.