반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- python
- 데이터분석
- FirebaseV9
- selenium
- 딥러닝
- 정치인
- 앱개발
- clone coding
- 리액트네이티브
- React
- expo
- 강화학습 기초
- TeachagleMachine
- 강화학습
- Ros
- Instagrame clone
- pandas
- kaggle
- 클론코딩
- 크롤링
- 카트폴
- App
- 전국국밥
- 머신러닝
- coding
- ReactNative
- 조코딩
- redux
- 사이드프로젝트
- JavaScript
Archives
- Today
- Total
qcoding
[ReactNative_study_13]PanResponder (스크린 화면 터치감지) 본문
반응형
https://reactnative.dev/docs/panresponder
1) 스마트폰 화면에서 사용자의 터치입력을 받아서 위치를 변경할 수 있는 Api이다.
아래 처럼 여러 props가 있으며 docs를 통해서 사용법을 확인할 수 있다.
Object {
"getInteractionHandle": [Function getInteractionHandle],
"panHandlers": Object {
"onMoveShouldSetResponder": [Function onMoveShouldSetResponder],
"onMoveShouldSetResponderCapture": [Function onMoveShouldSetResponderCapture],
"onResponderEnd": [Function onResponderEnd],
"onResponderGrant": [Function onResponderGrant],
"onResponderMove": [Function onResponderMove],
"onResponderReject": [Function onResponderReject],
"onResponderRelease": [Function onResponderRelease],
"onResponderStart": [Function onResponderStart],
"onResponderTerminate": [Function onResponderTerminate],
"onResponderTerminationRequest": [Function onResponderTerminationRequest],
"onStartShouldSetResponder": [Function onStartShouldSetResponder],
"onStartShouldSetResponderCapture": [Function onStartShouldSetResponderCapture],
},
}
2) 사용법
- 화면상에 View를 움직이는 예제
// panResponder props 확인
const panResponder = useRef(
PanResponder.create({
// 화면을 터치한 것을 감지함
onStartShouldSetPanResponder: () => true,
// 실제 화면에 터치를 시작할 때 시작됨
onPanResponderGrant:()=>{
}
// 화면에 터치를 하고 움직일 때를 감지함
// 이동에 대한 props로 event와 gesture 값을 받을 수 있다.
// gesture내에 우리가 필요한 dx,dy 이동값이 들어있다.
onPanResponderMove: (evt , gesture) => {
console.log(ges)
},
//화면에 터치를 하고 손을 뗏을 때를 감지함
onPanResponderRelease: () => {
}
})
).current;
//console.log(gesture)값 확인
// 얼만큼 이동했는 지 dx,dy에 대한 값을 확인할 수 있다.
Object {
"_accountsForMovesUpTo": 27808094,
"dx": -1.9940185546875,
"dy": 145.654296875,
"moveX": 202.9888916015625,
"moveY": 518.626953125,
"numberActiveTouches": 1,
"stateID": 0.9849285425468876,
"vx": -0.11077880859375,
"vy": 0.0026109483506944445,
"x0": 204.98291015625,
"y0": 372.97265625,
}
전체코드 --> Animation으로 touch 후 되돌아 가기
import { Animated, PanResponder} from 'react-native'
// 이동에 필요한 초기위치를 설정한다.
const POSITION = useRef(new Animated.ValueXY({x:0,y:0})).current;
// 화면을 감지하기 위해 panResponder 사용
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
// 내부에서 dx,dy를 이용하여 setValue 메서드를 활용하여 x,y 위치값을 변경한다.
onPanResponderMove: (_, { dx, dy }) => {
POSITION.setValue({
x: dx,
y: dy,
});
},
// 손을 감지한 것을 떼고 났을 때 다시 원래 위치로 되돌아가는 애니메이션을
// 만들어줌. setValue()를 사용하면 animation없이 바로 되므로 애니메이션을
// 이용하여 부드럽게 원래 위치로 돌아가게 설정함.
// * start()를 까먹으면 안됨
onPanResponderRelease:()=>{
Animated.spring(POSITION,{
toValue:{
x:0,
y:0
},
useNativeDriver:true,
bounciness:15
}).start()
})
).current;
return (
<Container>
<AnimatedBox
style={{
borderRadius,
opacity,
transform: [...POSITION.getTranslateTransform()],
}}
// animation이 필요한 곳에 아래와 같이 panHandlers을 등록한다.
{...panResponder.panHandlers}
></AnimatedBox>
</Container>
)
전체코드 --> touch 하는 데로 계속 움직이게 함.
const panResponder = useRef(
PanResponder.create({
// 터치가 시작되면 감지
onStartShouldSetPanResponder: () => true,
// 터치 시작될떄 실행되는 함수
// setOffset은 터치가 시작될 때 값이 reset 되지 않고 저번 터치가 시작됐을 때
// 위치에서 다시 시작되기 위해 사용함
onPanResponderGrant: () => {
console.log("Touch Started");
POSITION.setOffset({
x: POSITION.x._value,
y: POSITION.y._value,
});
},
onPanResponderMove: (_, { dx, dy }) => {
console.log("Finger Moving");
POSITION.setValue({
x: dx,
y: dy,
});
},
// touch가 완료 된 후에 offset 값이 계속 적산된 것을 막기 위해서
// offset을 reset 시키기 위함 POSITION.flattenOffset();
onPanResponderRelease:()=>{
console.log("Touch Finished");
POSITION.flattenOffset();
}
})
).current;
전체코드 --> 여러애니메이션 중첩해서 사용함
import React,{useState,useRef} from 'react'
import { Animated,View,Dimensions,PanResponder,StyleSheet} from 'react-native'
import styled from 'styled-components/native'
import { Ionicons } from "@expo/vector-icons";
const {width:SCREEN_WIDTH,height:SCREEN_HEIGHT}=Dimensions.get("window")
const Container=styled.View`
flex:1;
justify-content:center;
align-items:center;
background-color:rgba(9, 132, 227,0.7);
`;
const Box=styled.View`
background-color:white;
justify-content:center;
align-items:center;
width:200px;
height:200px;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2);
`;
const AnimatedBox=Animated.createAnimatedComponent(Box);
const AnimatedBox_OneLine = styled(Animated.createAnimatedComponent(View))`
background-color: white;
width: 200px;
height: 200px;
justify-content: center;
align-items: center;
border-radius: 12px;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2);
`;
//
const App = () => {
// touch 시 scale 변경을 위한 초기값설정
const scale=useRef(new Animated.Value(1)).current;
// Position 위치 변경을 위한 초기값지정
const position_x=useRef(new Animated.Value(0)).current;
// touch 시 scale up
const scaleUP=()=>{Animated.spring(scale,{
toValue:1.1,
useNativeDriver:true
}).start()
}
// touch 후 scale down
const scaleDown=()=>{Animated.spring(scale,{
toValue:1,
useNativeDriver:true
}).start()
}
// touch 후 왼쪽 오른쪽으로 많이 이동하지 않는 경우
// center로 돌아옴
const goCenter=()=>{
Animated.spring(position_x,{
toValue:0,
useNativeDriver:true
}).start();
}
// 왼쪽으로 이동하는 애니메이션
const goLeft=()=>{
Animated.spring(position_x,{
toValue:-500,
useNativeDriver:true
}).start();
}
// 오른쪽으로 이동하는 애니메이션
const goRight=()=>{
Animated.spring(position_x,{
toValue:500,
useNativeDriver:true
}).start();
}
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderGrant: () => {
scaleUP();
},
onPanResponderMove: (evt,{dx}) => {
scaleUP();
position_x.setValue(dx)
},
onPanResponderRelease:(evt,{dx})=>{
// 최종위치를 보고 위치를 변경함.
console.log(dx)
if(dx<-200){
goLeft();
scaleDown();
}
else if(dx>200){
goRight();
scaleDown();
}else{
// 동시에 animation 되는 걸 활용할 때에는 parallel을 사용함.
Animated.parallel([goCenter(), scaleDown()])
}
}
})
).current;
return (
<Container>
<AnimatedBox
{...panResponder.panHandlers}
// 2개의 style object를 적용함.
style={[
styles.elevation,
{
transform:[{translateX:position_x},{scale:scale}]
}
]}
>
<Ionicons name='airplane-sharp' size={70} color="black"></Ionicons>
</AnimatedBox>
</Container>
)
}
// android의 경우는 elevation api을 사용하여 그림자를 만들 수 있음
const styles = StyleSheet.create({
elevation: {
elevation: 20,
shadowColor: 'black',
},
})
export default App
반응형
'ReactNative' 카테고리의 다른 글
[ReactNative_study_15]LayoutAnimation (0) | 2021.12.20 |
---|---|
[ReactNative_study_14] useContext , Realm SDK DB (0) | 2021.12.20 |
[ReactNative_study_12]Animated 사용법 및 사용규칙 (0) | 2021.12.11 |
[ReactNative_Study_11]무한스크롤 구현 (Flat List & React query) (0) | 2021.12.06 |
[React_Native_Study_10]React query 사용하여 검색기능 활용 (0) | 2021.11.30 |
Comments