μ λ 1.0.0-rcλ‘ μμ νκ³ μμ΅λλ€.
drag-around-naive
:
const boxTarget = {
drop(props, monitor, component) {
const item = monitor.getItem();
const delta = monitor.getDifferenceFromInitialOffset();
const left = Math.round(item.left + delta.x);
const top = Math.round(item.top + delta.y);
component.moveBox(item.id, left, top);
}
};
νμ¬λ μλ νλͺ©μ νμ΄μ§μμ μ€νμ μ κ°μ ΈμμΌ νλ κ² κ°μ΅λλ€. κ·Έλ° λ€μ λλ‘ν νμ΄μ§μμ μ€νμ μ μ°Ύμ λ€μ νμ΄μ§μμ λλ‘ μ»¨ν μ΄λμ μ€νμ μ μ°Ύμ λ€μ μνν΄μΌ ν©λλ€. κ·Έ κ³μ°κ³Ό λ΄ λλ‘ λμ 컨ν μ΄λμ μλμ μΈ μμΉκ° μμ΅λλ€.
μ΄κ²μ κ½€ μΌλ°μ μΈ κ²μ λν λ§μ μμ μ²λΌ 보μ λλ€ ...
getClientOffset
κ° λ·°ν¬νΈμ μλμ μΈ μμΉλ₯Ό λ°ννλ κ² κ°μ΅λλ€. λ°λΌμ λκΈ° λμμμ μ€νμ
μ μ°ΎκΈ°λ§ νλ©΄ λ©λλ€. λκΈ° λμμ λΉν΄ νΈλ¦¬ν λ°©λ²μ μ¬μ©νλ κ²μ΄ μ¬μ ν κ°μΉκ° μλ€κ³ μκ°νμλκΉ?
μ, λμΉμ μν΄ μ΄κ²μ κ°μ§ μ μλ€κ³ μκ°ν©λλ€. μ§κΈμ findDOMNode(component).getBoundingClientRect()
λ§ μ¬μ©ν μ μμ§λ§ λ λ§μ μ¬λλ€μ΄ μ§μμ μμ±μΌλ‘ μλ €μ€λ€λ©΄ μ΄ κΈ°λ₯μ μΆκ°νλ κ²μ΄ μ’μ΅λλ€. μ΄κ²μ μ΄μ΄λκ³ λ€λ₯Έ μ¬λλ€μ΄ λ§νλ κ²μ λ΄
μλ€.
μ λ μ΄λ°κ² μμμΌλ©΄ ν©λλ€. λκΈ° λμμ κ²½κ³ μ§μ¬κ°ν/μ’νλ₯Ό κ°μ ΈμμΌ νλ―λ‘ λμ μμ λ§μ°μ€λ₯Ό μ¬λ € λμΌλ©΄ λκΈ° λμ λ΄λΆμ μΌμͺ½, μ€λ₯Έμͺ½, μμͺ½ λλ μλμͺ½μ μλμ§ κ³μ°ν μ μμ΅λλ€.
μλ μ’νλ λ€λ₯Έ μ¬μ© μ¬λ‘μ μ μ©ν μ μμ΅λλ€. Trelloμ μ μ¬ν μ±μ κ²½μ° λͺ©λ‘ μλ‘ μΉ΄λλ₯Ό λλκ·Ένλ©΄ λλ‘ μμμ νλ¨ κ·Όμ²μ λ§μ°μ€λ₯Ό κ°μ Έκ°λ©΄ λͺ©λ‘μ΄ νλ¨μΌλ‘ μ€ν¬λ‘€λκ³ μλ¨ κ·Όμ²μ λ§μ°μ€λ₯Ό κ°μ Έκ°λ©΄ μλ‘ μ€ν¬λ‘€λ©λλ€.
μ¬μ©μ 곡κ°μμ ꡬννκΈ°κ° μ½μ§ μμ΅λλ€.
λν κ²½κ³ μ¬κ°νμ μ‘μΈμ€νλ©΄ λΈλΌμ°μ μμ 리νλ‘μ°κ° νΈλ¦¬κ±°λκ³ λ€μ λΉμ©μ΄ λ λ€λ κ²μ μ½μ κΈ°μ΅μ΄ μ΄λ ΄νμ΄ μμ΅λλ€. μ΄κ²μ΄ μ¬μ ν μ¬μ€μΈμ§ νμ€νμ§ μμ΅λλ€.
νλͺ©μ΄ μ΄λνλμ§ μ μ μκΈ° λλ¬Έμ μ€μ λ‘ getBoundingClientRect
μ‘μΈμ€νμ§ μκ³ μ΄ μμ
μ μνν μ μλ λ°©λ²μ΄ μλ€κ³ μκ°ν©λλ€.
Trelloμ μ μ¬ν μ±μ κ²½μ° λͺ©λ‘ μλ‘ μΉ΄λλ₯Ό λλκ·Ένλ©΄ λλ‘ μμμ νλ¨ κ·Όμ²μ λ§μ°μ€λ₯Ό κ°μ Έκ°λ©΄ λͺ©λ‘μ΄ νλ¨μΌλ‘ μ€ν¬λ‘€λκ³ μλ¨ κ·Όμ²μ λ§μ°μ€λ₯Ό κ°μ Έκ°λ©΄ μλ‘ μ€ν¬λ‘€λ©λλ€.
μ’μ μ¬μ© μ¬λ‘μ λλ€.
μ±λ₯ ν¨λν°λ μ€μ λ‘ μ€μνλ©° React DnDμ μΆκ°λμμ§λ§ μ±μμ μ¬μ©νμ§ μμΌλ©΄ λλΉλ©λλ€. λ°λΌμ λλ μ΄κ²μ React DnDμ μΆκ°νκ³ μΆμ§ μμ΅λλ€.
μ¬μ©μ μμμμ ꡬννκΈ° μ½κ³ getBoundingClientRect
νΈμΆμ μ‘°μ νκ±°λ κ΄λ ¨ μ€ν¬λ‘€ μ½λλ₯Ό μ λλ©μ΄μ
νλ μμ λ£λ κ²κ³Ό κ°μ μμ
μ μνν μ μμ΅λλ€.
μ λ λΆλ₯ κ°λ₯ν μ€νΈλ μ€ ν
μ€νΈμ "μλ₯Ό λ€μ΄" "νλ¨μ λ§μ°μ€λ₯Ό μ¬λ € λμ λ μ€ν¬λ‘€"μ μΆκ°ν μ μμ΅λλ€. μ¬κΈ°μλ hover
λ§ μμ νκ³ μ λλ©μ΄μ
νλ μ λ΄μμ μ€ν¬λ‘€νλ 컨ν
μ΄λ μμ€μμ λ€λ₯Έ λκΈ° λμμ μΆκ°νλ κ²μ΄ ν¬ν¨λ©λλ€.
κ·Έλ¬λ μμμ μ€λͺ ν μ΄μ λ‘ DOM μ’ν λ©μλλ₯Ό React DnDμ μΆκ°νμ§ μκ² μ΅λλ€.
@gaearon μΌλ°νλ μ루μ
μ κ΄μ¬μ΄ μμ΅λλ€. μ΄λ»κ² μ°λ¦¬κ° μ¬μ©ν μμλ react-dnd-html5-backend
λμ getBoundingClientRect
μ§μ ?
DropTargetMonitor
ν¨μ getInitialSourceClientOffset
λ° getSourceClientOffset
λ₯Ό λ΄ onDrop
μ΄λ²€νΈ λ΄μ μ½λ°± ν¨μμ μ λ¬νμ¬ μ΄ λ¬Έμ λ₯Ό ν΄κ²°νμ΅λλ€. μ΄λ κ² νλ©΄ λ΄ μ½λ°± ν¨μκ° λ·° ν¬νΈμ κ΄λ ¨λ μ¬λ°λ₯Έ μ’νλ₯Ό κ³μ°ν μ μμ΅λλ€.
// some code before...
const [, dropRef] = useDrop({
accept: 'STICKY',
drop(item, monitor) {
move(
item.id,
monitor.getInitialSourceClientOffset(),
monitor.getSourceClientOffset()
);
},
});
// I'm updating my state with npm immer (immutable helper) throuthg the produce function...
const move = (id, initialPosition, finalPosition) => {
setList(
produce(list, draft => {
list.map(item => {
if (item.id === id) {
item.position = getCorrectDroppedOffsetValue(
initialPosition,
finalPosition
);
}
return item;
});
})
);
};
// and finally, my getCorrectDroppedOffsetValue function
const getCorrectDroppedOffsetValue = (initialPosition, finalPosition) => {
// get the container (view port) position by react ref...
const dropTargetPosition = ref.current.getBoundingClientRect();
const { y: finalY, x: finalX } = finalPosition;
const { y: initialY, x: initialX } = initialPosition;
// calculate the correct position removing the viewport position.
// finalY > initialY, I'm dragging down, otherwise, dragging up
const newYposition =
finalY > initialY
? initialY + (finalY - initialY) - dropTargetPosition.top
: initialY - (initialY - finalY) - dropTargetPosition.top;
const newXposition =
finalX > initialX
? initialX + (finalX - initialX) - dropTargetPosition.left
: initialX - (initialX - finalX) - dropTargetPosition.left;
return {
x: newXposition,
y: newYposition,
};
};
findDOMNode
λ κΈ°λ₯ κ΅¬μ± μμμ ν¨κ» μλνμ§ μμΌλ©° useDrop#drop
λ component
λ₯Ό μ λ¬νμ§ μμ΅λλ€. μ΄μ λ΄ κ΅¬μ± μμμ ref
λ₯Ό μ»μΌλ €λ©΄ λ³λλ‘ μ μ₯νκ³ μλμΌλ‘ λλ‘ μ»€λ₯ν°λ₯Ό νΈμΆνμ¬ μ λ¬ν©λλ€. μ΄ μμ
μ μννλ λ κ°κ²°ν λ°©λ²μ΄ μμ΅λκΉ?
function useCustomDrop(onDrop: (info: unknown, xy: Point) => void) {
const ref = useRef<Element>();
const [, dropTarget] = useDrop<any, void, unknown>({
accept: 'item-type',
drop(item, monitor) {
const offset = monitor.getSourceClientOffset();
if (offset && ref.current) {
const dropTargetXy = ref.current.getBoundingClientRect();
onDrop(item.data, {
x: offset.x - dropTargetXy.left,
y: offset.y - dropTargetXy.top,
});
}
}
});
return (elem) => {
ref.current = elem;
dropTarget(ref);
};
}
@quanganhtran 곡μ νκ³ μΆμ μμ ν μ½λ μνμ΄ μμ΅λκΉ?
@dendrochronology
μΈμμ μΈ μ: https://codesandbox.io/s/elastic-liskov-00ldf
APIλ ref
μ§μ μ μ₯ν νμκ° μμ λ λ μ’μ΅λλ€( useGlobalDrop
vs useLocalDrop
). μ΄μ μλ§ κ²½μ° ref
λ΄κ° μκ°νλ, react-dnd
μ΄λ―Έ μ»μ ~ λ€μ λΆμ°©λμ§ monitor
κ°μ²΄ ~ μ΄λκ°μ (μ κ·Ό drop
, λ΄κ° λμ΄ μ견), κ·Έκ²μ μ΄κ²μ ν΄κ²°ν κ²μ
λλ€.
μ΄ μ루μ μ νΉν λΈλΌμ°μ λ₯Ό νλνκ±°λ μ₯μΉ ν΄μλλ₯Ό λ³κ²½ν λ μ λ’°ν μ μμ΅λλ€. μ΄λ€ μκ°?
λλ κ°μ μ§λ¬Έμ΄ μμ΅λλ€ @ sepehr09
ꡬκΈλ§ λͺ λ² νλ€κ° κ·Έλ₯ μ§λμ³€λλ°... μλ μ§λ¬Έμ λν μ λ°μ΄νΈκ° μμ΅λκΉ? (λλ‘ λμμ κΈ°μ€μΌλ‘ λλ‘λ νλͺ©μ x/y νλ)
λλ μ΄κ²μ νμλ‘νλ μ¬λλ€μ λͺ©λ‘μ ν©λ₯ ν κ²μ΄λΌκ³ μκ°ν©λλ€. λμμ΄ νμνμΈμ?
μ΄ κΈ°λ₯μ λ§€μ° νμνλ©° λΌμ΄λΈλ¬λ¦¬μ μΆκ°ν΄μΌ νλ€κ³ μκ°ν©λλ€. λ°λ‘ μ§κΈ, μμ ν μ¬λμ΄ μμ΅λλ€. λμμ£ΌμΈμ!
κ°μ₯ μ μ©ν λκΈ
μ, λμΉμ μν΄ μ΄κ²μ κ°μ§ μ μλ€κ³ μκ°ν©λλ€. μ§κΈμ
findDOMNode(component).getBoundingClientRect()
λ§ μ¬μ©ν μ μμ§λ§ λ λ§μ μ¬λλ€μ΄ μ§μμ μμ±μΌλ‘ μλ €μ€λ€λ©΄ μ΄ κΈ°λ₯μ μΆκ°νλ κ²μ΄ μ’μ΅λλ€. μ΄κ²μ μ΄μ΄λκ³ λ€λ₯Έ μ¬λλ€μ΄ λ§νλ κ²μ λ΄ μλ€.