React documentation doesn’t have anything about handling animations that are not CSS transitions, such as animation of scroll position and SVG attributes.
As for CSS transitions, there is an add-on.
Here is a simple SVG example example:
/**
* @jsx React.DOM
*/
function animate(duration, onStep) {
var start = Date.now();
var timer = {id: 0};
(function loop() {
timer.id = requestAnimationFrame(function() {
var diff = Date.now() - start;
var fraction = diff / duration;
onStep(fraction);
if (diff < duration) {
loop();
}
});
})();
return timer;
}
function lerp(low, high, fraction) {
return low + (high - low) * fraction;
}
var App = React.createClass({
getInitialState: function() {
return {x: 0}
},
move: function(i) {
this.setState({x: this.state.x + i * 100});
},
render: function() {
return <div className="ShowerItem">
<p>
<button onClick={this.move.bind(this, -1)}>Left</button>
<button onClick={this.move.bind(this, 1)}>Right</button>
</p>
<svg><Dot x={this.state.x}/></svg>
</div>;
}
});
var Dot = React.createClass({
getInitialState: function() {
return {
x: 0,
final: 0
};
},
timer: null,
render: function() {
var from = this.state.x;
var to = this.props.x;
if (to !== this.state.final) {
this.state.final = to;
if (this.timer) {
cancelAnimationFrame(this.timer.id);
}
this.timer = animate(500, function(fraction) {
var x = lerp(from, to, fraction);
if (fraction >= 1) {
this.setState({
value: to
});
this.timer = null;
} else {
this.setState({x: x});
}
}.bind(this))
}
return <circle r="10" cy="10" cx={this.state.x + 10}/>
}
});
React.renderComponent(
<App/>,
document.body
);
Is there a more efficient way of doing animations?
It the code architecture right?
CSS Transitions add-on doesn't help here since I don't use CSS.
The easiest way to implement animations with CSS is using the transition property. We will be taking an in-depth look at CSS transitions and how to use them to create animations with React 18. Let's get started!
A production-ready motion library for React. Utilize the power behind Framer, the best prototyping tool for teams. Proudly open source.
I successfully used this project in my react-hammer integration project there are some examples with hammer events and react animation.
Here code of animated "BlinkingThing":
var BlinkingThing = React.createClass({
mixins: [React.Animate],
blink: function () {
var that = this;
var animateAfter = function () {
that.animate({
color: 'green'
}, that.props.blinkBack);
};
this.animate({
color: 'yellow'
}, this.props.blinkTo, animateAfter);
},
componentDidReceiveProps: function () {
this.setState({color: this.props.color})
},
componentDidMount: function () {
this.setState({color: this.props.color})
},
receiveHammerEvent: function (ev) {
if (ev) {
var value = ev.type;
switch (value) {
case 'tap':
this.blink();
break;
}
}
},
getInitialState: function () {
return {};
},
render: function () {
var style = {
display: 'inline-block',
backgroundColor: this.state.color
};
return (<div style={style}>{this.props.children}</div>);
}
});
You need some parent component which will propagate side effects(touch events, for example) to trigger changes of state in BlinkingThing component (animation rely on state changing when you call this.animate func), I made a HitArea component to do that. It calls receiveHammerEvent func from its children passing hammer event when it occurs.
Been having the same exact problems myself, until recently I've found out about Rekapi. This library provides state-based animations tools. Check out the tutorial https://github.com/jeremyckahn/rekapi/blob/master/docs/getting_started.md
The trick is, the context doesn't have to be a canvas or a DOM element, it can be a plain object, i.e. a component instance or a mixin, so this opens the possibility either to perform some logic in your actor's render method and then setState on your component(context), or simply write a "one trick actor" that always forwards its state to the component each frame.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With