React Native Animated to scale an image

44,106

I think this is what you want:

enter image description here

The animation is actually very smooth, doesn't look so in the GIF because the GIF is 4 Frames Per Second. Here is the code (Since your numbers are all constants, I just hard coded all of them in the below code):

import React, { Component } from 'react'
import { Animated, View, TouchableOpacity, Easing,Text} from 'react-native'

const backgroundImage = require('....')

class App extends Component {
    constructor(props) {
        super(props)
        this.animatedValue = new Animated.Value(0)
    }

    handleAnimation = () => {
        Animated.timing(this.animatedValue, {
            toValue: 1,
            duration: 1000,
            easing: Easing.ease
        }).start()
    }

    render() {
        return (
            <View style={{ flex: 1 }}>
                <TouchableOpacity onPress={this.handleAnimation}>
                    <Text>
                       Transform Image
                    </Text>
                </TouchableOpacity>
                <Animated.Image
                    source={backgroundImage}
                    resizeMode='cover'
                    style={{
                        position: 'absolute',
                        left: 40,
                        top: 100,
                        height: 20,
                        width: 20,
                        transform: [
                            {
                                translateX: this.animatedValue.interpolate({
                                    inputRange: [0, 1],
                                    outputRange: [0, 120]
                                })
                            },
                            {
                                translateY: this.animatedValue.interpolate({
                                    inputRange: [0, 1],
                                    outputRange: [0, 25]
                                })
                            },
                            {
                                scaleX: this.animatedValue.interpolate({
                                    inputRange: [0, 1],
                                    outputRange: [1, 15]
                                })
                            },
                            {
                                scaleY: this.animatedValue.interpolate({
                                    inputRange: [0, 1],
                                    outputRange: [1, 12.5]
                                })
                            }
                        ]
                    }}
                />
            </View>
        )
    }
}

export default App

Some explanation:

  1. After the animation, image's width becomes 300, which is 280 pixels larger, since the image scales up from the center, therefore, the image's x coordination has left shifted 140 px, or -140 px, And we want the x coordinate to left shift only 20 px, hence, we should right shift it 120 px, that's why the output range of x is [0, 120]

  2. Same reason why y's output range is [0, 25]

  3. width is now 300 compared to before 20, which is 15 times larger

  4. height is now 250 compared to before 20, which is 12.5 times larger

Share:
44,106
Somename
Author by

Somename

Interested in building responsive database driven websites and application. Beginner level but quick learner.

Updated on July 29, 2022

Comments

  • Somename
    Somename almost 2 years

    I have 2 issues with the Animated API.

    1st: I am able to show the Image from left to right with the following code. I want to scale the Image from position X=40 (leftPadding), Y=100(topPadding), height:20, width:20 to X=20, Y=10, height:250, width:300. How do I achieve this?

    My code:

    import React, { Component } from 'react';
    import { StyleSheet, Text, Image, Animated, Easing, View, Button } from 'react-native';
    
    class MyTestComp extends Component {
      componentWillMount() {
        this.animatedValue = new Animated.Value(0);
      }
      buttonPress(){
      this.animatedValue.setValue(0);
        Animated.timing(this.animatedValue,{
          toValue:1,
          duration:1000,
          Easing: Easing
        }).start()
      }
    
      render() {
    
        const translateX = this.animatedValue.interpolate({
          inputRange: [0, 1],
          outputRange: [-500, 1]
        })
    
        const transform = [{translateX}];
    
        return (
          <View>
            <Text>MyTestComp</Text>
            <Animated.View style={transform}>
            <Image
              source={require('./assets/17.jpg')}
              style={{width:300, height:250}}
            />
            </Animated.View>
            <View style={{marginTop:10}}>
              <Button title="Click Me" onPress={()=> this.buttonPress()} />
            </View>
          </View>
        );
      }
    }
    
    
    export default MyTestComp;
    

    2nd: Everytime I run the animation, I'm getting an exception:

    enter image description here

    I'm not able to find any documentation on this. How do I use the transform prop.

    Many thanks.

  • Somename
    Somename about 6 years
    What do I do in case of undefined width? Say I want the width to fit the entire screen, and i can find the width from Dimensions. But how do I calculate the outputRange for ScaleX? Thanks.
  • Somename
    Somename about 6 years
    I got that working used ((width-150)/2)-20 where width => let width = Dimensions.get('window').width