Last active
October 17, 2021 11:13
-
-
Save cmmartin/a46d1b706dab4fab96f8a7617b66dcc0 to your computer and use it in GitHub Desktop.
React Native HOC for easily adding spring animations to your components
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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