Skip to content

Instantly share code, notes, and snippets.

@cmmartin
Last active October 17, 2021 11:13
Show Gist options
  • Save cmmartin/a46d1b706dab4fab96f8a7617b66dcc0 to your computer and use it in GitHub Desktop.
Save cmmartin/a46d1b706dab4fab96f8a7617b66dcc0 to your computer and use it in GitHub Desktop.
React Native HOC for easily adding spring animations to your components
/*
* EXAMPLE USAGE
* This component is text that will bounce on mount and
* every time `this.props.someProperty` changes.
* Too bad react native doesn't support decorators yet :/
*/
import React, {
Component,
StyleSheet,
Animated,
} from 'react-native'
import SpringAnimation from './SpringAnimation'
class BouncingTextExample extends Component {
render() {
const { style } = this.props
return (
<Animated.Text style={[styles.text, style]}>
{ 'Example!' }
</Animated.Text>
)
}
}
export default SpringAnimation(animationOptions)(BouncingTextExample)
const animationOptions = {
friction: 4,
animateOnMount: true,
// warning: don't use an arrow function here :)
shouldAnimate: function (nextProps) {
return this.props.someProperty != nextProps.someProperty
}
}
const styles = StyleSheet.create({
text: {
fontSize: 24,
}
})
/*
* This HOC simply passes its wrapped component a style prop
* which does the animation. Make sure to forward it down to the element
* you want to animate. The component to animate must be a native Animated component.
* (Animated.Text, Animated.View, Animated.Image)
*
* // For example, the magic is in `this.props.style`...
* render() {
* return <Animated.Text style={[ styles.text, this.props.style ]} />
* }
*/
import React, { Component, Animated } from 'react-native'
export default function ({
// bounce on mount?
animateOnMount = true,
// will be called in componentDidUpdate
// return a bool to control whether animation fires
shouldAnimate = nextProps => true,
// scale to 1.5x the normal size
startScale = 1.5,
// bounce back to the normal size
endScale = 1,
// super bouncy
friction = 1,
}) {
const SpringAnimation = ComposedComponent => class SpringAnimationHOC extends Component {
state = {
bounceValue: new Animated.Value(startScale),
}
render() {
const { bounceValue } = this.state
return (
<ComposedComponent
style={{ transform: [{ scale: bounceValue }] }}
{ ...this.props } />
)
}
componentDidMount() {
if (animateOnMount) this._animate()
}
componentDidUpdate(...args) {
if (shouldAnimate.call(this, ...args)) this._animate()
}
_animate() {
this.state.bounceValue.setValue(startScale)
Animated.spring(
this.state.bounceValue,
{
toValue: endScale,
friction,
}
).start();
}
}
return SpringAnimation
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment