Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I animate the width of a button based on percentage, and the same for it's backgroundColor?

Tags:

I have some <AnimatedButton />

I want to animate it to go from 100% width to 40% width depending on a prop that is a boolean called isFullWidth.

I have:

class AnimatedButton extends Component {     constructor(props) {       super(props);       this.state = { width: new Animated.Value(100) };     }     toggleWidth() {       const endWidth = this.props.isFullWidth ? 40 : 100;        Animated.timing(this.state.width, {         toValue: endWidth,         duration: 200,         easing: Easing.linear,       }).start();     }      render() {       <TouchableOpacity        style={{ width: `${this.state.width}%` }}        onPress={this.props.onPress}       >        // more stuff       </TouchableOpacity>     } } 

The problem is that it just jumps into the appropriate percentage without animating. I tried setting the width to just this.state.animatedValue and rather than use percentage, just use pixels, e.g. 150 to 400 and back, and it works fine as expected.

Same question applies for going from say rgba(220, 100, 50, 0.8) to rgba(30, 70, 30, 1.0) and back?

like image 432
VDog Avatar asked Feb 12 '18 05:02

VDog


1 Answers

I would suggest you to read more about interpolation because it is very useful when doing almost any kind of animation in React Native.

Basically with interpolate you can map some animated values to so other values. In your case you want to map number between 40-100 to a percent string like 50%. Second thing you want to do is to map number between 40-100 to color from (as an example) red to blue.

Read interpolate docs fully and experiment with it and ask if you have questions after that :)

So I would do it like this:

class AnimatedButton extends Component {   constructor(props) {     super(props);     this.state = { width: new Animated.Value(100) };   }    toggleWidth() {     const endWidth = this.props.isFullWidth ? 40 : 100;      Animated.timing(this.state.width, {       toValue: endWidth,       duration: 200,       easing: Easing.linear,     }).start();   }    render() {     <TouchableOpacity       style={{         width: this.state.width.interpolate({           inputRange: [0, 1],           outputRange: ['0%', '100%'],         }),         backgroundColor: this.state.width.interpolate({           inputRange: [40, 100],           outputRange: ['rgba(30, 70, 30, 1.0)', 'rgba(220, 100, 50, 0.8)'],         }),       }}       onPress={this.props.onPress}     >       // more stuff     </TouchableOpacity>;   } } 
like image 82
Henrik R Avatar answered Sep 18 '22 16:09

Henrik R