728x90
* SwipeItem.js 전체코드
import React from "react"; import styled from "styled-components"; import img from "./scc_img01.png"; //memoziation 은 여러번 랜더가 이루어지지않게 방어해준다고 보면된다. React.memo() const SwipeItem = React.memo(({ onSwipe }) => { const swipe_div = React.useRef(null); //함수형컴포넌트에서 ref잡는법 // 현재 swipe 상태 let swipe_status = "ready"; //나중에 이친구가 애니메이팅 효과를 주기위해 미리 작성한 코드 (스와이프했을때 자연스럽게 움직이게 하기위함) let target_classname = ""; //시작위치를 기록해놔야 이벤트가 동작할때 기록을 하기위함 (터치시작을 기록한 변수를 선언한 코드) let coordinate = { start_x: 0, start_y: 0, end_x: 0, end_y: 0, }; //useEffect를 통해 이벤트리스너는 처음한번만 등록해주면된다. 처음 한번만 등록할때는 대괄호도 붙여줘야한다. React.useEffect(() => { const reset = () => { // console.log("in reset"); swipe_status = "ready"; coordinate = { start_x: 0, start_y: 0, end_x: 0, end_y: 0, }; swipe_div.current.className = target_classname; swipe_div.current.style.left = 0 + "px"; swipe_div.current.style.top = 0 + "px"; }; //리셋에서는 coordinate, className, left,top 모두 원래대로 돌려놓아야한다. 초기값으로 const touchStart = (e) => { // e 라는건 이벤트 객체를 가져온다고 보면된다. // 터치 시작 시, swipe_status를 touchstart로 변경해줍니다. // 그리고 터치 시작한 좌표를 기록합니다! // (중요! 그래야 터치 종료할 때 위치를 보고 왼쪽인지, 오른쪽인지 판별할 수 있다!) swipe_status = "touchstart"; target_classname = swipe_div.current.className; // console로 터치 이벤트가 시작될 때 좌표를 확인해볼까요? // console.log(e.touches[0]); // console.log(e.touches[0].clientX); // console.log(e.touches[0].clientY); // 좌표도 기록해줍니다 :) coordinate = { ...coordinate, start_x: e.touches[0].clientX, start_y: e.touches[0].clientY, }; }; const touchEnd = (e) => { swipe_status = "touchend"; // touchEnd이벤트는 touches 대신, changedTouches가 있어요. // console.log(e.changedTouches[0]); coordinate = { ...coordinate, end_x: e.changedTouches[0].clientX, end_y: e.changedTouches[0].clientY, }; // x좌표 이동 거리를 구해줍니다.(x좌표에 대한 차이를 구해야하므로 비교해주면된다) let diff_x = coordinate.end_x - coordinate.start_x; // 스와이프 방향 / 기본은 left로 뒀습니다! let direct = "left"; // Match.abs() : 절대값을 구해주는 친구입니다. // 기존에 className에 swipe라는 className를 추가해주겠다는 의미이며, // 아래 &.swipe {} 이런식으로 연결하여 추가로 SCSS문법에 따라 꾸며줄 수 있다. if (Math.abs(diff_x) > 50) { swipe_div.current.className = target_classname + " swipe"; // 움직인 방향에 따라 더 옴직이고 투명도를 0으로 (점점 사라지게) 줘봐요! if (diff_x > 0) { // console.log('move right'); direct = "right"; //이벤트 동작 후 한번에 이동하지않고 부드럽게 이동될 수 있도록 함 swipe_div.current.style.left = diff_x + 150 + "px"; swipe_div.current.style.opacity = 0; } else { direct = "left"; // console.log('move left'); // console.log(diff_x - 150); swipe_div.current.style.left = diff_x - 150 + "px"; swipe_div.current.style.opacity = 0; } // 300 ms후 reset 해줍니다! // 이 300ms는 props로 받아서 처리해줘도 좋겠네요! // props로 받아온, 콜백 함수도 여기서 처리해줄게요! window.setTimeout(() => { reset(); //터치무브하면서 움직여놓은게 있기때문에 리셋을 한번 해줘야한다. onSwipe(direct); }, 300); return; } // reset 해줍니다. reset(); }; const touchMove = (e) => { // 스와이프 중 다른 이벤트가 발생하는 것을 막아줍니다 e.preventDefault(); // console.log("in touch move!"); // 현재 좌표(이동 중인 좌표)를 기록해준다. 이미지가 이동할때 기록된 좌표를 토대로 움직여주기위해 let current_coordinate = { x: e.touches[0].clientX, y: e.touches[0].clientY, }; // 콘솔로 이동한 값이 어떻게 나오는 지 한번 확인해볼까요? // console.log( // current_coordinate.x - coordinate.start_x, // current_coordinate.y - coordinate.start_y // ); // 터치 중일 때 div가 따라 움직이도록 해주는데 움직인만큼만 움직이도록 한다. swipe_div.current.style.left = current_coordinate.x - coordinate.start_x + "px"; swipe_div.current.style.top = current_coordinate.y - coordinate.start_y + "px"; }; // 터치 이벤트가 취소될 경우 원래 상태로 돌려줍니다! const touchCancel = (e) => { swipe_status = "cancel"; reset(); }; //터치이벤트 등록 해주는 부분(이벤트 리스너) swipe_div.current.addEventListener("touchstart", touchStart); swipe_div.current.addEventListener("touchend", touchEnd); swipe_div.current.addEventListener("touchmove", touchMove); swipe_div.current.addEventListener("touchcancel", touchCancel); // 이부분은 이벤트 해제 부분이에요! return () => { // 만약 이벤트 걸었던 엘리먼트가 없으면 해제하지 않습니다! 그냥 리턴해준다. if (!swipe_div.current) { return; } swipe_div.current.removeEventListener("touchstart", touchStart); swipe_div.current.removeEventListener("touchend", touchEnd); swipe_div.current.removeEventListener("touchmove", touchMove); swipe_div.current.removeEventListener("touchcancel", touchCancel); }; }, []); return ( <DragItem ref={swipe_div}> <img src={img} /> </DragItem> //DragItem 에서 swipe를 적용하려고하는것이므로, 여기에다가 ref 먼저 잡아줘야한다. ); }); const DragItem = styled.div` display: flex; align-items: center; justify-content: center; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; &.swipe { transition: 300ms; } & > div { border-radius: 500px; background-color: #ffd6aa; } & img { max-width: 150px; } `; SwipeItem.defaultProps = { onSwipe: (direction) => {}, }; // props가 없을때 화면에서 에러가나는걸 방지하기위해 기본적으로 이 props는 어떤값을 가지고 있다라고 알려준다. export default SwipeItem; |
'내마음대로만들어보자 > React' 카테고리의 다른 글
[Store] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.11 |
---|---|
[Router/Redux] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.09 |
[Swipe] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.08 |
[조건부렌더링/state 데이터 관리] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.08 |
[퀴즈,점수화면 뷰만들기] 우정테스트 사이트 만들기(Feat.리액트) (0) | 2021.08.05 |