영상 더블 탭 추가하기

dudgus5766·2023년 3월 5일
0

Junior Developer

목록 보기
16/18

Baund의 영상화면을 탭(tap) 후 나타나는 seek bar를 작년에 개발했습니다.


🔼 드래그를 통해서 사용자가 원하는 영상의 위치에 도달하게 해줌

그 이후, 논의를 거쳐 더블 탭스킵버튼을 이용한 스킵 기능이 추가되었습니다.


더블탭 예시 사진


📍 TapGestureHandler

TapGestureHandler 는 태그 내부에 포함된 View의 탭을 조절합니다. (Handler 컴포넌트를 중첩시켜 singleTapdoubleTap 활성화할 수 있습니다.)

화면에서의 탭 동작

1️⃣ singleTap : video 메인 화면(프로필, 설명, 아이콘 등 노출) ↔  seek bar

2️⃣ doubleTap : skip forward rewind 기능 구현


📍 로직 구현하기

// videoItem.js

const videoItem = () => {
	const doubleTap = useRef(React.createRef().current);

  const onSingleTap = (event) => {
    if (event.nativeEvent.state === State.ACTIVE) {
      console.log('single tap!');
    }
  };
  const onDoubleTap = (event) => {
    if (event.nativeEvent.state === State.ACTIVE) {
      console.log('double tap!');
    }
  };

  return (
    <TapGestureHandler onHandlerStateChange={onSingleTap} waitFor={doubleTap}>
      <TapGestureHandler ref={doubleTap} onHandlerStateChange={onDoubleTap} numberOfTaps={2}>
        <View />
      </TapGestureHandler>
    </TapGestureHandler>
  );
};

onHandlerStateChange 콜백 함수로 onVideoDoubleTap 함수를 호출하게 되는데, 파라미터로 사용자 tab의 위치를 알려주는 point의 x 와 y 값을 넘겨줍니다.

point.x 값을 통해 화면의 좌측인 지(rewind), 우측인 지(forward) 확인할 수 있었습니다👆

// 화면 더블 탭 - 좋아요
  const onVideoDoubleTap = (point) => {
    // point의 x값이 화면 왼쪽을 터치할 때
    if (point.x < width / 2) {
      controlSkipRewind();
    }
    // point의 x값이 화면 오른쪽을 터치할 때
    else {
      controlSkipForward();
    }
  };
/**
    더블 탭 rewind skip 함수
   */
 
const controlSkipRewind = () => {
    let rewindTime = currentPosition - SKIP_TIME;

    // skip Animated.Value 적용 함수
    skipAnimationRewind();

    if (rewindTime < 0) { // 만약 -10초를 했을 때 0초 미만일 때 0초로 맞춰줌
      rewindTime = 0;
    }

    setCurrentPosition(rewindTime); //현재 시간 업데이트
    setMoveDirection(SeekBarMoveDirectionType.BACKWARD); //현재 상태 업데이트

    videoProps?.videoRef?.seek(rewindTime); //Video 컴포넌트의 ref에 seek 함수에 시간 추가
  };

📍UI 그리기

디자인 팀에게 받은 프로토파이 작업물을 보니, 더블탭 후에 화면에 나타나야하는 요소들이 3가지가 있었습니다.

  • background: opacity가 들어간 하얀 반원 모양 배경
  • lottie: 빨리감기 icon 로티
  • text: +10초, -10초 텍스트

문제는 각자 다른 타이밍으로 애니메이션이 들어가야 한다는 것이었습니다. (특히 backgroundtextlottie 와 다르게 애니메이션이 스멀스멀(부드럽게?) 나왔다가 사라졌습니다.)

그래서 skip의 애니메이션 총 시간을 500ms로 설정한 후, background는 나타날 때 (opacity value가 0 → 1 로 바뀔 때) 260ms, 사라질 때(opacity value가 1 → 0 로 바뀔 때)) 240ms를 적용하였습니다.

그리고 마지막으로 Animated.sequence를 사용해 각각의 애니메이션을 묶고 Animated.Parallel로 한꺼번에 실행해주었습니다.

/**
    skip 적용 animation
   */

const rewindSkipOpacityAnimation = Animated.sequence([
    Animated.timing(animatedRewindSkipOpacity, {
      toValue: 1,
      duration: 260,
      useNativeDriver: true,
    }),
    Animated.timing(animatedRewindSkipOpacity, {
      toValue: 0,
      duration: 240,
      useNativeDriver: true,
    }),
  ]);

  const rewindSkipProgressAnimation = Animated.sequence([
    Animated.timing(animatedRewindSkipProgress, {
      toValue: 1,
      duration: 500,
      useNativeDriver: true,
    }),
    Animated.timing(animatedRewindSkipProgress, {
      toValue: 0,
      duration: 0,
      useNativeDriver: true,
    }),
  ]);

  const skipAnimationRewind = () => {
    Animated.parallel([rewindSkipOpacityAnimation, rewindSkipProgressAnimation]).start();
  };
profile
RN App Developer

0개의 댓글