본문 바로가기
코딩생활/ReactNative

[React Native] 3-7 Animated로 애니메이션 적용

by InfoJun 2023. 3. 17.
반응형

지금 FeedList에는 사용자 경험과 관련해 한 가지 문제가 있습니다.

 

내용이 많아지면 우측 하단의 버튼이 항목의 내용을 가리게 됩니다.

 

이 문제를 해결 하기 위해선 사용자가 스크롤을 최하단으로 내릴 때 해당 버튼을 숨겨야됩니다.

 


애니메이션 연습히기

리액트 네이티브에서 에니메이션을 구현할 때는 animated라는 객체를 사용합니다.

 

import React,{useRef} from 'react';
import {Animated} from 'react-native';

function Sample() {
	const animation = useRef(new Animated.Value(1)).current
}

 

Value를 만들 때는 이렇게 useRef를 사용해야 합니다.

 

이전엔 컴포넌트 레퍼런스에 포커스를 줄 때 사용하였는데 

 

래퍼런스 선택 외에 컴포넌트 생성 시에 설정하고 , 사라질 때까지 재사용 하고 싶을 때도 사용하여 구현할 수 있습니다.

 

<Animated.View style={{opacity: animation}}></Animated.View>

 

Animated. 뒤에 사용하고 ㅣㅍ은 리액트 네이티브 컴포넌트의 이름을 넣어주면 됩니다.

 

이 예시 코드에서는 컴포넌트의 투명도 값을 animation이 가르키고 있는 값으로 설정했습니다.

 

추후 이 값을 변경할 때는 Animation.timing이라는 함수를 사용해야 합니다.

 

Animated.timing(animation. {
	toValue : 0, // 어떤 값으로 변경할지 -필수
    duration : 1000, // 애니메이션에 걸리는 시간(밀리세컨드) - 기본값 : 500
    delay : 0, // 딜레이 이후 에니메이션 시작 - 기본값 : 0
    useNativeDriver: true , // 네이티브 드라이버 사용 여부 - 필수
    isInteraction : true, // 사용자 인터렉션에 의해 시작된 애니메이션인지 지정 - 기본값 : true
    // 애니메이션 속도 변경 함수 - 기본 값 : Easing.inOt(Easing.ease)
    easing: Easing.inOut(Easing.ease),
}).start(() => {
	// 애니메이션 처리 완료 후 실행할 작업
})

 

여기서 toValue, useNativeDriver값은 필수로 지정해야 합니다.

 

useNativeDriver는 애니메이션 처리 작업을 자바스크립트 엔진이 아닌 

 

네이티브 레벨에서 진행하게 하는 옵션이며 tranfroms, opacity처럼 

 

레이아웃과 관련 없는 스타일에만 적용할 수 있습니다.

 

애니메이션은 .start()로 시작하고

 

이 함수 끝에 콜백 함수를 인자로 넣어주면 에니메이션이 끝난 후 호출됩니다.

 

이제 CalendarScreen에 연습을 하겠습니다.

 

Fade In ,Fade Out 효과 입니다.

 

screens/CalendarScreen.js

import React, {useRef} from 'react';
import {View, StyleSheet, Text, Animated, Button} from 'react-native';

function FadeInAndOut() {
  const animation = useRef(new Animated.Value(1)).current;

  return (
    <View>
      <Animated.View
        style={[
          styles.rectangle,
          {
            opacity: animation,
          },
        ]}
      />
      <Button
        title={'FadeIn'}
        onPress={() => {
          Animated.timing(animation, {
            toValue: 0,
            useNativeDriver: true,
          }).start();
        }}
      />
    </View>
  );
}

function CalendarScreen() {
  return (
    <View style={styles.block}>
      <FadeInAndOut />
    </View>
  );
}

const styles = StyleSheet.create({
  block: {},
  rectangle: {
    width: 100,
    height: 100,
    backgroundColor: 'black',
  },
});

export default CalendarScreen;

 

지금은 두개의 버튼으로 하였지만 

 

상태값에 따라 하나의 버튼으로 하고싶다면 useState와 useEffect를 사용합니다.

 

screens/CalendarScreen.js

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

function FadeInAndOut() {
  const animation = useRef(new Animated.Value(1)).current;
  const [hidden, setHidden] = useState(false);
  useEffect(() => {
    Animated.timing(animation, {
      toValue: hidden ? 0 : 1,
      useNativeDriver: true,
    }).start();
  }, [hidden, animation]);

  return (
    <View>
      <Animated.View
        style={[
          styles.rectangle,
          {
            opacity: animation,
          },
        ]}
      />
      <Button
        title={'Toggle'}
        onPress={() => {
          setHidden(!hidden);
        }}
      />
    </View>
  );
}

function CalendarScreen() {
  return (
    <View style={styles.block}>
      <FadeInAndOut />
    </View>
  );
}

const styles = StyleSheet.create({
  block: {},
  rectangle: {
    width: 100,
    height: 100,
    backgroundColor: 'black',
  },
});

export default CalendarScreen;

 

이번엔 좌우로 움직이기를 구현해보겠습니다.

 

컴포넌트를 움직일 때는 꼭 필요하지 않다면 left,top 스타일 보다는 tarnsfrom 스타일을 사용하는 것이

 

성능면에서 더 좋습니다.

 

{
	tarnfrom : [{translateX: 100} , {translsateY: 50}]
}

 

다음 코드를 기존 FadeInAndOut 컴포넌트를 지우고 만들어 봅시다.

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

function SlideLeftAndRight() {
  const animation = useRef(new Animated.Value(1)).current;
  const [enable, setEnable] = useState(false);
  useEffect(() => {
    Animated.timing(animation, {
      toValue: enable ? 150 : 0,
      useNativeDriver: true,
    }).start();
  }, [enable, animation]);

  return (
    <View>
      <Animated.View
        style={[
          styles.rectangle,
          {
            transform: [{translateX: animation}],
          },
        ]}
      />
      <Button
        title={'Toggle'}
        onPress={() => {
          setEnable(!enable);
        }}
      />
    </View>
  );
}

function CalendarScreen() {
  return (
    <View style={styles.block}>
      <SlideLeftAndRight />
    </View>
  );
}

const styles = StyleSheet.create({
  block: {},
  rectangle: {
    width: 100,
    height: 100,
    backgroundColor: 'black',
  },
});

export default CalendarScreen;

 

이제 버튼을 누르면 오른쪽 왼쪽으로 움직이는 사각형을 확인할 수 있습니다.

 

이번엔 interpolate로 여러 스타일을 적용해보겠습니다

 

anination.interpolate({
	inputRatne : [0,1],
    outputRange: [0, 150]
})

 

사용법은 위와 같이 사용하면 됩니다. 

 

screens.CalendarScreen.js

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

function SlideLeftAndRight() {
  const animation = useRef(new Animated.Value(1)).current;
  const [enable, setEnable] = useState(false);
  useEffect(() => {
    Animated.timing(animation, {
      toValue: enable ? 150 : 0,
      useNativeDriver: true,
    }).start();
  }, [enable, animation]);

  return (
    <View>
      <Animated.View
        style={[
          styles.rectangle,
          {
            transform: [
              {
                translateX: animation.interpolate({
                  inputRange: [0, 1],
                  outputRange: [0, 150],
                }),
              },
            ],
            opacity: animation.interpolate({
              inputRange: [0, 1],
              outputRange: [1, 0],
            }),
          },
        ]}
      />
      <Button
        title={'Toggle'}
        onPress={() => {
          setEnable(!enable);
        }}
      />
    </View>
  );
}

function CalendarScreen() {
  return (
    <View style={styles.block}>
      <SlideLeftAndRight />
    </View>
  );
}

const styles = StyleSheet.create({
  block: {},
  rectangle: {
    width: 100,
    height: 100,
    backgroundColor: 'black',
  },
});

export default CalendarScreen;

 

이젠 정사각형이 오른쪽으로 가면서 사라지고 왼쪽으로 오면서 나타나는 것을 확인 할 수 있습니다.

반응형

댓글