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>
)
}
드래그하고있는 아이템의 스타일을 변경하기 위해,
가장 먼저 드래그 상태인지를 추적해야한다.
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>
)
}
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 }}
...
}
위에서 생성한 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>
}