속도기준 Snap point 구하기 feat. Velocity with reanimated

Darcy Daeseok YU ·2022년 11월 21일
0

reanimated로 스프링 에니메이션 Swipeable 카드를 구현중에 속도 인자에 대한 계산이 필요해서 계산 함수를 가져왔다.

출처: https://github.com/wcandillon/react-native-redash

library를 가져다 쓰면 편하다.

함수 내부적으로 어떻게 돌아가는지 모르고 그냥 가져다 쓸려니 뭔가 똥멍청이가 되는 느낌이랄가...
그래서 해당 부분만 가져와서 뜯어본다.

Snap point with velocity

사용자가 오브젝트를 드래그 할때 velocity(속도)에 따른 이동거리 계산하기

구현 목표 : 3 of snap points

드래그 했을 경우 현재 위치값과 관성에 따른 이동거리를 더하여 가까운 snap point를 찾는다.

드래그가 충분하지 않을경우 원점
오브젝트 넓이의 반이하를 드래그 했을 경우 버튼 표시
오브젝트 넓이의 반이상을 드래그 했을 경우 바로 삭제

velocity  => 3000 means => 3000px / 초 (1초당 3000px 드래그) 

제 기준으로 이해하기 위해서 예시를 만들었습니다. 정확하지 않음...
아시는 분 답글 남겨주시면 대단히 감사하겠습니다.

const snapPoint = (
 	// 현재위치
	currentPositionX: number,
    // 드래그 종료시 오브젝트가 가지는 이동 속도 (방향성 가짐 왼쪽: 마이너스) 
    velocity: number,
    // threadhold 같은 일정 지점을 어레이형태로 정해준다. 
    snapPoints : number[], 
    ) => {
    
    // 까먹지 마세요. UI Tread 사용을 위함.!!! 
	'worklet';
        
        
        
    // 입력값 1: 
    // currentPositionX : 200 (이전드래그 후 중간지점에 머므르고있음) 
    // velocity : -3000 (매우빠르게 왼쪽으로 드래그)
   
    const SCREEN_WIDTH = 400
    snapPoints : [SCREEN_WIDTH, SCREEN_WIDTH / 2 , 0]
    
    
    // 속도 기준으로 멈출 위치 = 현재 위치 + 관성에 따른 이동거리 20% 
    const pointBasedOnVelocity = currentPositionX + veloctiy * 0.2(inertia)
    
	// deltas [] => 각 스냅포인트 - 현재위치 + 관성 이동거리 
    // 절대값을 적용하여 각 스냅포인트 별 이동후 포인트와 거리(diff)를 어레이 형식으로 반환
    const deltas = snapPoints.map(piont=> Math.abs(pointBasedOnVelocity - point))
    
    // (각 스냅포인트 - 현재위치 + 관성 이동거리) 값이 제일 작은 값을 찾는다. 
    // (각 스냅포인트 - 현재위치 + 관성 이동거리) 값이 적을 수록 스냅포인트에 가까움.    
    const minDelta = Math.min(...deltas) 
    
    
    // 스냅포인트 값을 찾아 반환한다.     
    const snapPoint = snapPoints.find(snapP => Math.abs(pointBasedOnV - snapP) === minDelta)

	return snapPoint;
}

아래는 예시

const dragX = 200
const velocity = 175 //175(원점으로 복원)  475(중간지점 멈춤) 1475(화면영역에서 사라짐) 
const SCREEN_WIDTH = 400;
const snapPoints = [SCREEN_WIDTH,(SCREEN_WIDTH / 2) , 0]
const pointBasedOnV = dragX + velocity * 0.2
const deltas = snapPoints.map(snapP =>Math.abs( pointBasedOnV-snapP))
const minDelta = Math.min(...deltas)
const result = snapPoints.filter(snapP => Math.abs(pointBasedOnV - snapP)===minDelta)

기억 저장소 : darcy's

profile
React, React-Native https://darcyu83.netlify.app/

0개의 댓글