Frontend/React-Native

[React Native] Animated Interpolate extrapolate

w00se 2021. 8. 16. 00:38

https://pixabay.com/ko/photos/놀이터-회전-신장-매력-5188459/

Animated의 Interpolate는 활용도가 높은 메서드입니다.

 

이번 글에서는 Interpolate의 설정 값 중 extrapolate에 대해서 정리하려 합니다.

 

extrapolate는 Animated value가 interpolate의 inputRage 범위를 벗어났을 때 값을 처리하는 방법에 대한 설정입니다.

React Native 공식 문서에 따르면 extrapolate에는 아래와 같이 총 세 종류의 값을 설정할 수 있습니다.

 

1. extend

2. identity

3. clamp

 

1. extend

extrapolate의 default 값으로 extrapolate에 별도의 값을 설정하지 않으면 기본으로 extend가 설정 됩니다.

extend는 Animated Value가 inputRage를 벗어나도 현재의 mapping을 그대로 유지시키는 설정입니다.

 

해당 코드는 Animated Value에 따라 view의 x position을 조정하는 코드로 주요 변수에 대한 설명은 아래와 같습니다.

- animatedValue: Animated.Timing으로 직접 변화를 주는 변수입니다. 1초 동안 0에서 (화면 너비) * 2 - 100까지 선형적으로 변화를 줬습니다.

 

- translateX: animatedValue에 interpolate 값을 적용한 후 반환되는 값으로, inputRage: [0, 300]이며 outRage: [0, 150]입니다.

 

import React, { useRef, useEffect } from 'react';
import {
    View,
    StyleSheet,
    Dimensions,
    Animated
} from 'react-native';

const win = Dimensions.get("window");

function InterpolateTestScreen(props) {
    const animatedValue = useRef(new Animated.Value(0)).current
    const translateX = animatedValue.interpolate({
        inputRange: [0, 300],
        outputRange: [0, 150],
        extrapolate: "extend"
    })

    useEffect(()=>{
        Animated.timing(animatedValue, {
            toValue: win.width * 2 - 100,
            duration: 1000,
            delay: 3000,
            useNativeDriver: true,
        }).start();
    }, []);

    return (
        <View style={styles.rootContainer}>
            <View style={styles.skyblueBox}/>
            <View style={styles.grayBox}/>
            <Animated.View style={[ styles.circle, { transform: [{ translateX: translateX }] } ]}/>
        </View>
    )
}

const styles = StyleSheet.create({
    rootContainer: {
        flex: 1,
    },
    skyblueBox: {
        marginTop: 100,
        width: 150,
        height: 30,
        backgroundColor: "#96C0CE",
    },
    grayBox: {
        width: 300,
        height: 30,
        backgroundColor: "#74828F",
    },
    circle: {
        marginTop: 50,
        marginBottom: 50,
        width: 50,
        height: 50,
        borderRadius: 25,
        backgroundColor: "#C25B56",
    },
});

export default InterpolateTestScreen;

 

 

extrapolate에 extend를 적용했을 때 해당 코드에서 animatedValue와 translateX는 아래 표처럼 mapping 됩니다.

animatedValue translateX
0 0
100 50
150 75
200 100
250 125
300 150
350 175
400 200
450 225

 

코드를 실행한 화면 결과는 아래와 같습니다.

 

extend 적용 모습

 

2. identity

identity는 interpolate에서 Animated value가 inputRage의 범위를 벗어났을 때 mapping에 관계없이 animated value를 그대로 반환해주는 설정입니다.

 

identity를 적용한 코드는 아래와 같습니다.

import React, { useRef, useEffect } from 'react';
import {
    View,
    StyleSheet,
    Dimensions,
    Animated
} from 'react-native';

const win = Dimensions.get("window");

function InterpolateTestScreen(props) {
    const animatedValue = useRef(new Animated.Value(0)).current
    const translateX = animatedValue.interpolate({
        inputRange: [0, 300],
        outputRange: [0, 150],
        extrapolate: "identity"
    })

    useEffect(()=>{
        Animated.timing(animatedValue, {
            toValue: win.width * 2 - 100,
            duration: 1000,
            delay: 3000,
            useNativeDriver: true,
        }).start();
    }, []);

    return (
        <View style={styles.rootContainer}>
            <View style={styles.skyblueBox}/>
            <View style={styles.grayBox}/>
            <Animated.View style={[ styles.circle, { transform: [{ translateX: translateX }] } ]}/>
        </View>
    )
}

const styles = StyleSheet.create({
    rootContainer: {
        flex: 1,
    },
    skyblueBox: {
        marginTop: 100,
        width: 150,
        height: 30,
        backgroundColor: "#96C0CE",
    },
    grayBox: {
        width: 300,
        height: 30,
        backgroundColor: "#74828F",
    },
    circle: {
        marginTop: 50,
        marginBottom: 50,
        width: 50,
        height: 50,
        borderRadius: 25,
        backgroundColor: "#C25B56",
    },
});

export default InterpolateTestScreen;

 

extrapolate에 identity를 적용했을 때 해당 코드에서 animatedValue와 translateX는 아래 표처럼 mapping 됩니다.

 

animatedValue translateX
0 0
100 50
150 75
200 100
250 125
300 150
350 350
400 400
450 450

 

코드를 실행한 화면 결과는 아래와 같습니다.

하늘색 박스의 너비가 150이며, 빨간색 원이 해당 지점부터 이동되는 속도가 증가하는 것을 확인할 수 있습니다.

 

identity 적용 모습

 

3. clamp

clamp는 interpolate에서 Animated value가 inputRage의 범위를 벗어났을 때 outputRage의 최대(또는 최소) 값을 반환합니다.

즉, inputRange안에서 만 값의 변화가 있고 Animated Value가 inputRange를 벗어나면 변화가 없습니다.

 

clamp를 적용한 코드는 아래와 같습니다.

import React, { useRef, useEffect } from 'react';
import {
    View,
    StyleSheet,
    Dimensions,
    Animated
} from 'react-native';

const win = Dimensions.get("window");

function InterpolateTestScreen(props) {
    const animatedValue = useRef(new Animated.Value(0)).current
    const translateX = animatedValue.interpolate({
        inputRange: [0, 300],
        outputRange: [0, 150],
        extrapolate: "clamp"
    })

    useEffect(()=>{
        Animated.timing(animatedValue, {
            toValue: win.width * 2 - 100,
            duration: 1000,
            delay: 3000,
            useNativeDriver: true,
        }).start();
    }, []);

    return (
        <View style={styles.rootContainer}>
            <View style={styles.skyblueBox}/>
            <View style={styles.grayBox}/>
            <Animated.View style={[ styles.circle, { transform: [{ translateX: translateX }] } ]}/>
        </View>
    )
}

const styles = StyleSheet.create({
    rootContainer: {
        flex: 1,
    },
    skyblueBox: {
        marginTop: 100,
        width: 150,
        height: 30,
        backgroundColor: "#96C0CE",
    },
    grayBox: {
        width: 300,
        height: 30,
        backgroundColor: "#74828F",
    },
    circle: {
        marginTop: 50,
        marginBottom: 50,
        width: 50,
        height: 50,
        borderRadius: 25,
        backgroundColor: "#C25B56",
    },
});

export default InterpolateTestScreen;

 

extrapolate에 clamp를 적용했을 때 해당 코드에서 animatedValue와 translateX는 아래 표처럼 mapping 됩니다.

animatedValue translateX
0 0
100 50
150 75
200 100
250 125
300 150
350 150
400 150
450 150

 

코드를 실행한 화면 결과는 아래와 같습니다.

하늘색 박스의 너비가 150이며, 빨간색 원이 해당 지점까지만 이동하는 걸 확인할 수 있습니다.

 

clamp 적용 모습

 


참고 자료

https://reactnative.dev/docs/animatedvalue#interpolate - React Native 공식 문서

 

읽어 주셔서 감사합니다 :)

잘못된 부분이 있다면 댓글로 편히 알려주세요😊