[framer motion] DND 하는 동안 아이템 스타일 조작하기

sumi-0011·2023년 6월 26일
0
post-thumbnail

drag and drop을 구현할 때,
드래그 하는 아이템을 직관적으로 보여주기 위해 box-shadow, background-color를 조작해보자

시작 코드

참고 링크

List.tsx

import { Reorder } from "framer-motion"
import { useState } from "react"

function List() {
  const [items, setItems] = useState([0, 1, 2, 3])
  
  return (
    <Reorder.Group axis="y" values={items} onReorder={setItems}>
      {items.map((item) => (
        <Reorder.Item key={item} value={item}>
          {item}
        </Reorder.Item>
      ))}
    </Reorder.Group>
  )
}

DNDItem.tsx

const DNDItem = ({item}) => {
	const dragControls = useDragControls();
  
	return (
		<Reorder.Item
          	value={item}
          	dragControls={dragControls}
	    	dragListener={false}
          >
			<Icon 
              onPointerDown={(e) => controls.start(e)}
            />
		</Reorder.Item>		
	)
}

드래그하는 아이템의 스타일 변경하기

step 1 : 드래그 감지하기

드래그하고있는 아이템의 스타일을 변경하기 위해,
가장 먼저 드래그 상태인지를 추적해야한다.

onDragStart, onDragEnd 이벤트를 통해 이벤트 동작 시작, 끝을 감지한다.

const DNDItem = ({item}) => {
   const dragControls = useDragControls();
  
   const onDragEnd = () => {
      // 드래그 동작 끝
    };

    const onDragStart = () => {
      // 드래그 동작 시작
    };
	return (
		<Reorder.Item
          	value={item}
          	dragControls={dragControls}
	    	dragListener={false}
 			onDragEnd={onDragEnd}
      		onDragStart={onDragStart}
          >
			<Icon 
              onPointerDown={(e) => controls.start(e)}
            />
		</Reorder.Item>		
	)
}

2. motion value를 생성한다.

framer-motion 라이브러리는 motionValue를 제공한다.

motionValue가 : motion의 value 즉 움직임에 대한 database
사용 이유
1. motionValue가 변수처럼 작용한다.
2.기존 값에 변화를 줄 수 있게 된다.
참고 : motionValue

이 motionValue를 통해서 boxShadow, backgroundColor를 조작하려고 한다.
드래그 할 때는 boxShadow를 어두운 검정색으로 설정하고, backgroundColor를 옅은 파랑색으로 설정한다.
드래그 하는 상태가 아닐때는 boxShadow, backgroundColor를 흰색으로 보여주려 한다.

따라서 밑과 같이 초기값, 그리고 motionValue를 생성한다.
그리고 컴포넌트에 연결한다.

const inactiveShadow = '0px 0px 0px rgba(255, 255, 255, 0.8)';
const inactiveBackground = '#fff';

const activeShadow = '0px 8px 32px rgba(0, 0, 0, 0.24)';
const activeBg = '#F2F5FF';

const DNDItem = ({item}) => {
  ...
  const backgroundColor = useMotionValue(inactiveBackground);
  const boxShadow = useMotionValue(inactiveShadow);

  ...
  
  return (
     <Reorder.Item
       style={{ boxShadow, y, backgroundColor }}
  ...
}

step 3 : 드래그 시작, 끝에서 스타일을 변경한다.

위에서 생성한 motionValue를 조작하여 스타일을 변경한다.

드래그 할 때는 boxShadow를 어두운 검정색으로 설정하고, backgroundColor를 옅은 파랑색으로 설정한다.
드래그 하는 상태가 아닐때는 boxShadow, backgroundColor를 흰색으로 보여주려 한다.

이와 같은 요구사항을 충족하기 위해
드래그 시작에는 boxShadow를 activeShadow로 설정하고, backgroundColor를 activeBg로 설정한다.
드래그 끝에는 반대로 boxShadow를 inactiveShadow로, backgroundColor를 inactiveBackground로 설정한다.

  const onDragEnd = () => {
    animate(boxShadow, inactiveShadow);
    animate(backgroundColor, inactiveBackground);
  };

  const onDragStart = () => {
    animate(boxShadow, activeShadow);
    animate(backgroundColor, activeBg);
  };

완성 코드

const inactiveShadow = '0px 0px 0px rgba(255, 255, 255, 0.8)';
const inactiveBackground = '#fff';

const activeShadow = '0px 8px 32px rgba(0, 0, 0, 0.24)';
const activeBg = '#F2F5FF';

const DNDItem = ({item}) => {
  const dragControls = useDragControls();

  const backgroundColor = useMotionValue(inactiveBackground);
  const boxShadow = useMotionValue(inactiveShadow);

  const onDragEnd = () => {
    animate(boxShadow, inactiveShadow);
    animate(backgroundColor, inactiveBackground);
  };

  const onDragStart = () => {
    animate(boxShadow, activeShadow);
    animate(backgroundColor, activeBg);
  };
  
  return (
     <Reorder.Item
       value={item}
       dragControls={dragControls}
       dragListener={false}
       onDragEnd={onDragEnd}
       onDragStart={onDragStart}
       style={{ boxShadow, y, backgroundColor }} >
  		<Icon  onPointerDown={(e) => controls.start(e)} />
	</Reorder.Item>	
}

완성 스크린샷

profile
안녕하세요 😚

0개의 댓글