qcoding

[ReactNative_study_12]Animated 사용법 및 사용규칙 본문

ReactNative

[ReactNative_study_12]Animated 사용법 및 사용규칙

Qcoding 2021. 12. 11. 16:31
반응형

* nomad coder React Native Master class 수강 하면서 정리하는 글

Animation 사용법

1)  useRef랑 같이 사용하는 이유

--> UI=Component(state), 로 UI는 state가 변경될 때 component가 다시 렌더링 되게 된다. 이때 리렌더링 되면 값이 초기값으로 적용이 되게 되는데, useRef()를 쓰면 새롭게 렌더링 되지 않고 값이 유지 되게 된다. 애니메이션이 되고 원래 위치로 돌아가는 것을 방지하는 데 사용한다. 즉, 리렌더링 시 값이 초기화 되는 것을 막기 위해서 사용한다.

import React,{useState,useRef} from 'react'
import { Animated,TouchableOpacity,Easing } from 'react-native'
import styled from 'styled-components/native'

const Container=styled.View`
  flex:1;
  justify-content:center;
  align-items:center;
  
`;

const Box=styled.View`
  background-color:red;
  width:200px;
  height:200px;
`;

const AnimatedBox=Animated.createAnimatedComponent(Box);



const App = () => {
  const [up, setUp] = useState(false)

// setUp을 변경하므로 component가 다시 리렌더링 될 때 초기화 되는 것을 막기위해서
// useRef를 사용한다.

  const Y = useRef(new Animated.Value(0)).current; 

  const moveUp = () => {
    Animated.timing(Y, {
      toValue: up?-200:200,
      useNativeDriver: true,
      easing: Easing.circle,
    }).start(()=>{
    // start가 끝나고 callback함수를 정의할 수 있음
      setUp((prev) => !prev)
    });
  };
  
  console.log(up)
  return (
    <Container>
      <TouchableOpacity style={{borderWidth:5,borderColor:"black", height:200}} onPress={moveUp}>
       <AnimatedBox 
        style={{
          transform: [{ translateY: Y }],
        }}></AnimatedBox>
      </TouchableOpacity>
     
    </Container>
  )
}

export default App

 

2) InterPolation --> 말 그대로 inputRange에 따른 outRange가 Interpolation 되서 return 되게 된다.

여기서 Input 과 Output은 array의 형태이며 동일한 length를 가져야 한다.

// Animation의 초기값을 설정한다.
const Y_POSITION = useRef(new Animated.Value(300)).current;


 const moveUp = () => {
 // timing animation을 적용할 value : Y_POSITION 와 option을 정한다.
 // start내에 callback 함수를 등록할 수 있다.
    Animated.timing(Y_POSITION, {
      toValue: up?300:-300,
      useNativeDriver: true,
      duration: 1000
    }).start(()=>{
      setUp((prev) => !prev)
    });
  };
  
  // 여기서는 Opacity 와 borderRadius 값을 outputRange로 받아서 사용하며,
  // Y_POSITION에 따라서 각각 변하는 값을 Inperpolation 한다. 
  // Inperpolation은 Animated.Value에 쓸 수 있는 함수이다.
    const opacity = Y_POSITION.interpolate({
    inputRange: [-300, 0, 300],
    outputRange: [1, 0.5, 1],
  });
  const borderRadius = Y_POSITION.interpolate({
    inputRange: [-300, 300],
    outputRange: [100, 0],
  });
  
  // Interpolation은 단순히 숫자만 되는 것이 아니라 
  // 아래처럼 문자와 숫자가 같이있는 곳에도 사용할수 있다.
  // 그러나 어떤것은 native driver에서 지원하지않기때문에
  // useNativeDriver: false로 바꿔주어야 할 때도 있다.
  const rotation = Y_POSITION.interpolate({
    inputRange: [-300, 300],
    outputRange: ["-360deg", "360deg"],
  });
  
  
  Y_POSITION.addListener(() => {
    console.log("Y VALUE:", Y_POSITION);
    console.log("opacity VALUE:", opacity);
    console.log("borderRadius VALUE:", borderRadius);
  });
  
    return (
    <Container>
      <Pressable style={{borderWidth:5,borderColor:"black"}} onPress={moveUp}>
       <AnimatedBox 
        style={{
          borderRadius,
          opacity,
          transform: [{rotateY:rotation},{ translateY: Y_POSITION }],
        }}></AnimatedBox>
      </Pressable>
     
    </Container>
  )

 

3) XY좌표/ getTranslateTransform/ Animation Loop / Sequence 

- XY좌표

const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("window");

// 화면 왼쪽 상단에서 시작하도록 초기값을 잡음
const POSITION = useRef(
    new Animated.ValueXY({
      x: -SCREEN_WIDTH / 2 + 100,
      y: -SCREEN_HEIGHT / 2 + 100,
    })
  ).current;

-getTranslateTransform : [{translateX: }, {translateY :}] 와 동일하게 한번에 배열로 받아주는 함수

       <AnimatedBox 
         style={{
			
            // X,Y 좌표를 각각 이동할 수 있게 설정하는 것
            transform: [{ translateX: POSITION.x }, { translateY: POSITION.y }],
            
            // 이 함수를 이용하면 위의 X,Y 좌표를 받오므로 아래와 같이 한번에 작성가능함
            transform: [...POSITION.getTranslateTransform()],
          }}
              ></AnimatedBox>

- Animation Loop / Sequence : Animation을 여러개 만들어서 이것을 sequence로 순서대로 실행하게 할 수 있다.

  // 화면의 구석으로 이동시키는 각각의 애니메이션
  const topLeft = Animated.timing(POSITION, {
    toValue: {
      x: -SCREEN_WIDTH / 2 + 100,
      y: -SCREEN_HEIGHT / 2 + 100,
    },
    useNativeDriver: false,
  });
  const bottomLeft = Animated.timing(POSITION, {
    toValue: {
      x: -SCREEN_WIDTH / 2 + 100,
      y: SCREEN_HEIGHT / 2 - 100,
    },
    useNativeDriver: false,
  });
  const bottomRight = Animated.timing(POSITION, {
    toValue: {
      x: SCREEN_WIDTH / 2 - 100,
      y: SCREEN_HEIGHT / 2 - 100,
    },
    useNativeDriver: false,
  });
  const topRight = Animated.timing(POSITION, {
    toValue: {
      x: SCREEN_WIDTH / 2 - 100,
      y: -SCREEN_HEIGHT / 2 + 100,
    },
    useNativeDriver: false,
  });
  
  // 여러 애니메이션을 sequnce로 연결해서 실행할 수 있다.
    const moveUp = () => {
    // loop를 쓰면 반복이 되고, sequnce안에 배열로 animation을 전달
    // start()를 써주어야 시작이 됨
    Animated.loop(
      Animated.sequence([bottomLeft, bottomRight, topRight, topLeft])
    ).start();
  };

 

 

 

Animated 사용의 규칙

 

1) value를 쓸 때에는 useState 등 을 이용하지 않고 Animated.Value()를 사용한다.

  ex) const Y=new  Animated.Value(0)

2) value에 절대값을 사용하지 않는다.

ex) let Y=new  Animated.Value(0) 
    Y=20 
    // 위와같이 Animation에 사용되는 값을 절대값으로 넣지 않음

 

3) Animated 에서 사용되는 components는 정해져 있다. 

 

< 사용가능한 components>

  • Animated.Image
  • Animated.ScrollView
  • Animated.Text
  • Animated.View
  • Animated.FlatList
  • Animated.SectionList

 * 만일 새롭게 만든 component를 사용하려면 createAnimatedComponent 메서드를 사용해야 한다.

  * styeld-component 사용 & createAnimatedComponent 를 사용하는 2가지 방법

1) 

// TouchableOpacity를 불러와야함
import { Animated,TouchableOpacity} from 'react-native'

const Box=styled(Animated.createAnimatedComponent(TouchableOpacity))`
  background-color:red;
  width:200px;
  height:200px;
`;

2) 

import { Animated } from 'react-native'

const Box=styled.TouchableOpacity`
  background-color:red;
  width:200px;
  height:200px;
`;


// 위에서 만든 Box를 가지고 Animatiton에서 사용될 Box를 새로만듦 
const AnimatedBox=Animated.createAnimatedComponent(Box);

 

반응형
Comments