React-dnd: 놓기 λŒ€μƒ μ»¨ν…Œμ΄λ„ˆλ₯Ό κΈ°μ€€μœΌλ‘œ λ–¨μ–΄λœ¨λ¦° ν•­λͺ©μ˜ μ’Œν‘œλ₯Ό μ–»μœΌλ €λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό ν•©λ‹ˆκΉŒ?

에 λ§Œλ“  2015λ…„ 05μ›” 13일  Β·  15μ½”λ©˜νŠΈ  Β·  좜처: react-dnd/react-dnd

μ €λŠ” 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);
  }
};

ν˜„μž¬λŠ” μ›λž˜ ν•­λͺ©μ˜ νŽ˜μ΄μ§€μ—μ„œ μ˜€ν”„μ…‹μ„ 가져와야 ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. 그런 λ‹€μŒ λ“œλ‘­ν•œ νŽ˜μ΄μ§€μ—μ„œ μ˜€ν”„μ…‹μ„ 찾은 λ‹€μŒ νŽ˜μ΄μ§€μ—μ„œ λ“œλ‘­ μ»¨ν…Œμ΄λ„ˆμ˜ μ˜€ν”„μ…‹μ„ 찾은 λ‹€μŒ μˆ˜ν–‰ν•΄μ•Ό ν•©λ‹ˆλ‹€. κ·Έ 계산과 λ‚΄ λ“œλ‘­ λŒ€μƒ μ»¨ν…Œμ΄λ„ˆμ— μƒλŒ€μ μΈ μœ„μΉ˜κ°€ μžˆμŠ΅λ‹ˆλ‹€.

이것은 κ½€ 일반적인 것에 λŒ€ν•œ λ§Žμ€ μž‘μ—…μ²˜λŸΌ λ³΄μž…λ‹ˆλ‹€ ...

enhancement

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

예, λŒ€μΉ­μ„ μœ„ν•΄ 이것을 κ°€μ§ˆ 수 μžˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. μ§€κΈˆμ€ findDOMNode(component).getBoundingClientRect() 만 μ‚¬μš©ν•  수 μžˆμ§€λ§Œ 더 λ§Žμ€ μ‚¬λžŒλ“€μ΄ 지원을 μŒμ„±μœΌλ‘œ μ•Œλ €μ€€λ‹€λ©΄ 이 κΈ°λŠ₯을 μΆ”κ°€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 이것을 열어두고 λ‹€λ₯Έ μ‚¬λžŒλ“€μ΄ λ§ν•˜λŠ” 것을 λ΄…μ‹œλ‹€.

λͺ¨λ“  15 λŒ“κΈ€

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 νšλ“)

λ‚˜λŠ” 이것을 ν•„μš”λ‘œν•˜λŠ” μ‚¬λžŒλ“€μ˜ λͺ©λ‘μ— ν•©λ₯˜ ν•  것이라고 μƒκ°ν•©λ‹ˆλ‹€. 도움이 ν•„μš”ν•˜μ„Έμš”?

이 κΈ°λŠ₯은 맀우 ν•„μš”ν•˜λ©° λΌμ΄λΈŒλŸ¬λ¦¬μ— μΆ”κ°€ν•΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. λ°”λ‘œ μ§€κΈˆ, μž‘μ—…ν•œ μ‚¬λžŒμ΄ μžˆμŠ΅λ‹ˆλ‹€. λ„μ™€μ£Όμ„Έμš”!

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰