손으로 혹은 버튼으로 카드 무한으로 좌 혹은 우로 날리기

import React, { useRef, useState } from 'react'
import { Animated, Easing, PanResponder } from 'react-native'
import styled from 'styled-components/native'
import { Ionicons } from '@expo/vector-icons'
import icons from './icons'

const Container = styled.View`
  flex: 1;
  justify-content: center;
  align-items: center;
  background-color: #00a8ff;
`
const Card = styled.View`
  width: 300px;
  height: 300px;
  background-color: white;
  justify-content: center;
  align-items: center;
  border-radius: 12px;
  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5);
  position: absolute;
`
const AnimatedCard = Animated.createAnimatedComponent(Card)

const Btn = styled.TouchableOpacity`
  margin: 0px 10px;
`

const BtnContainer = styled.View`
  flex-direction: row;
  flex: 1;
`
const CardContainer = styled.View`
  flex: 3;
  justify-content: center;
  align-items: center;
`

export default function App() {
  const scale = useRef(new Animated.Value(1)).current
  const position = useRef(new Animated.Value(0)).current
  const rotation = position.interpolate({
    inputRange: [-280, 280],
    outputRange: ['-15deg', '15deg'],
    extrapolate: 'clamp',
  })

  // position.addListener(() => console.log(rotation))

  const secondScale = position.interpolate({
    inputRange: [-300, 0, 300],
    outputRange: [1, 0.5, 1],
    extrapolate: 'clamp',
  })

  const onPressIn = Animated.spring(scale, {
    toValue: 0.8,
    useNativeDriver: true,
  })
  const onPressOut = Animated.spring(scale, {
    toValue: 1,
    useNativeDriver: true,
  })
  const goCenter = Animated.spring(position, {
    toValue: 0,
    useNativeDriver: true,
  })
  const goLeft = Animated.spring(position, {
    toValue: -700,
    useNativeDriver: true,
    tension: 2,
    restDisplacementThreshold: 100,
    restSpeedThreshold: 100,
  })
  const goRight = Animated.spring(position, {
    toValue: 700,
    useNativeDriver: true,
    tension: 5,
    restDisplacementThreshold: 100,
    restSpeedThreshold: 100,
  })

  const panResponder = useRef(
    PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onPanResponderMove: (_, { dx }) => {
        position.setValue(dx)
      },
      onPanResponderGrant: () => onPressIn.start(),
      onPanResponderRelease: (_, { dx }) => {
        if (dx < -250) {
          goLeft.start()
        } else if (dx > 250) {
          goRight.start()
        } else {
          Animated.parallel([onPressOut, goCenter]).start()
        }
      },
    })
  ).current
  const [index, setIndex] = useState(0)
  const onDismiss = () => {
    scale.setValue(1)
    position.setValue(0)
    setIndex((prev) => prev + 1)
  }
  const closePress = () => {
    goLeft.start(onDismiss)
  }
  const checkPress = () => {
    goRight.start(onDismiss)
  }
  return (
    <Container>
      <CardContainer>
        <AnimatedCard style={{ transform: [{ scale: secondScale }] }}>
          <Ionicons name={icons[index + 1]} color="#192a56" size={98} />
        </AnimatedCard>
        <AnimatedCard
          {...panResponder.panHandlers}
          style={{
            transform: [
              { scale: scale },
              { translateX: position },
              { rotateZ: rotation },
            ],
          }}
        >
          <Ionicons name={icons[index]} color="#192a56" size={98} />
        </AnimatedCard>
      </CardContainer>
      <BtnContainer>
        <Btn onPress={closePress}>
          <Ionicons name="close-circle" color="white" size={58} />
        </Btn>
        <Btn onPress={checkPress}>
          <Ionicons name="checkmark-circle" color="white" size={58} />
        </Btn>
      </BtnContainer>
    </Container>
  )
}
profile
코딩하는초딩쌤

0개의 댓글