React Native: Scaling Animation onPress Made Easy

In the world of touch screen and virtual buttons, providing visual feedback of an action is important to let your users know their touch interactions have been received by your app. If you find yourself rolling your own touchables in react native, you can use custom animations to respond to user interaction. Here’s a easy way to animate a the appearance of a “press”, which you can use in addition to other feedback, like opacity:

import * as React from 'react';
import { Animated, Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import { Constants } from 'expo';
// You can import from local files
import AssetExample from './components/AssetExample';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default class App extends React.Component {
scaleInAnimated = new Animated.Value(0);
scaleOutAnimated = new Animated.Value(0);
render() {
return (
<View style={styles.container}>
<TouchableOpacity
onPress={() => { console.warn("I did it!")}}
onPressIn={() => {SCALE.pressInAnimation(this.scaleInAnimated);}}
onPressOut={() => {SCALE.pressOutAnimation(this.scaleInAnimated);}}
style={SCALE.getScaleTransformationStyle(this.scaleInAnimated)}
>
<Animated.View>
<Card>
<AssetExample />
</Card>
</Animated.View>
</TouchableOpacity>
<View style={{margin: 10, height: 10}}/>
<TouchableOpacity
onPress={() => { console.warn("I did it!")}}
onPressIn={() => {SCALE.pressInAnimation(this.scaleOutAnimated);}}
onPressOut={() => {SCALE.pressOutAnimation(this.scaleOutAnimated);}}
style={SCALE.getScaleTransformationStyle(this.scaleOutAnimated, 1, 1.05)}
>
<Animated.View>
<Card>
<AssetExample />
</Card>
</Animated.View>
</TouchableOpacity>
</View>
);
}
}
// For large projects, this might better serve us exported from it's own file, so we could use it across man classes. i.e ./animations/scale.js
const SCALE = {
// … see full contents below, or at https://gist.github.com/JoeM-RP/608c155f317a80634c2d1dfa4b962c2b
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#fff',
padding: 18,
},
});

view raw
boldchips.js
hosted with ❤ by GitHub

Our animation is largely driven by these primary functions. Take a close look at getScaleTransformationStyle. We accept an Animated.Value, which is an object that describes the state of animation for a given element (or elements) on screen, as well as a start size (how large the element should be prior to animating) and an end size (how large the object should be at the end of the animation). “End” size is somewhat loose here, as we are relying on the touchable onPressOut (i.e – touch released) to return our element to it’s original state. Compare pressInAnimation to pressOutAnimation:

const SCALE = {
// this defines the terms of our scaling animation.
getScaleTransformationStyle(animated: Animated.Value, startSize: number = 1, endSize: number = 0.99) {
const interpolation = animated.interpolate({
inputRange: [0, 1],
outputRange: [startSize, endSize],
});
return {
transform: [
{ scale: interpolation },
],
};
},
// This defines animation behavior we expext onPressIn
pressInAnimation(animated: Animated.Value, duration: number = 150) {
animated.setValue(0);
Animated.timing(animated, {
toValue: 1,
duration,
useNativeDriver: true,
}).start();
},
// This defines animatiom behavior we expect onPressOut
pressOutAnimation(animated: Animated.Value, duration: number = 150) {
animated.setValue(1);
Animated.timing(animated, {
toValue: 0,
duration,
useNativeDriver: true,
}).start();
},
};

view raw
animations.js
hosted with ❤ by GitHub

You’ll notice that the animated.setValue value corresponds to the expected inputRange value defined by our interpolation variable in getScaleTransformationStyle. Once we apply the style returned from getScaleTransformationStyle to a valid Animated.View, we can see our scaling adventures in action! Check out the expo sandbox or the quick demo below:

Not too bad, eh? Don’t forget: you can make SCALE its own file and export it for further reuse across multiple files. Enjoy!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s