React-dnd: ¿Cómo obtengo las coordenadas de mi elemento soltado en relación con el contenedor de destino de colocación?

Creado en 13 may. 2015  ·  15Comentarios  ·  Fuente: react-dnd/react-dnd

Estoy trabajando con 1.0.0-rc.

En 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);
  }
};

En la actualidad, parece que necesito obtener el desplazamiento de la página del elemento original, luego puedo encontrar el desplazamiento de la página donde lo dejé caer, luego necesito encontrar el desplazamiento del contenedor de caída de la página, luego lo hago ese cálculo y tengo la posición relativa en mi contenedor de destino de caída.

Esto parece mucho trabajo para algo bastante común ...

enhancement

Comentario más útil

Sí, supongo que podríamos tener esto por simetría. Por ahora, puede usar findDOMNode(component).getBoundingClientRect() , pero no me importaría agregar esto si más personas expresan su apoyo. Mantengamos esto abierto y veamos qué dicen los demás.

Todos 15 comentarios

Parece que getClientOffset me devuelve la posición relativa a la ventana gráfica. Entonces, todo lo que tengo que hacer es encontrar mi compensación en mi destino de caída. ¿Crees que todavía vale la pena tener un método de conveniencia en relación con el objetivo de caída?

Sí, supongo que podríamos tener esto por simetría. Por ahora, puede usar findDOMNode(component).getBoundingClientRect() , pero no me importaría agregar esto si más personas expresan su apoyo. Mantengamos esto abierto y veamos qué dicen los demás.

También me gustaría algo como esto. Necesito obtener los rectángulos delimitadores / coordenadas del destino de colocación, de modo que cuando coloco el cursor sobre algo, puedo calcular si está en el lado izquierdo, derecho, superior o inferior dentro del destino de colocación.

Las coordenadas relativas pueden ser útiles para otros casos de uso. Para una aplicación similar a Trello, cuando arrastra una tarjeta sobre una lista, la lista se desplaza hacia la parte inferior cuando se sitúa cerca de la parte inferior del área de colocación y se desplaza hacia arriba cuando se desplaza hacia la parte superior.

Trivial de implementar en el espacio del usuario aunque.

Además, recuerdo vagamente haber leído que acceder al rectángulo delimitador desencadena el reflujo en los navegadores y es algo costoso. No estoy seguro de si este sigue siendo el caso.

No creo que haya una manera de hacer esto sin acceder a getBoundingClientRect porque nunca se sabe si el elemento se movió.

Para una aplicación similar a Trello, cuando arrastra una tarjeta sobre una lista, la lista se desplaza hacia la parte inferior cuando se sitúa cerca de la parte inferior del área de colocación y se desplaza hacia arriba cuando se desplaza hacia la parte superior.

Ese es un gran caso de uso.

La penalización de rendimiento es, de hecho, significativa y se desperdiciará si se agrega a React DnD pero su aplicación no la usa. Por lo tanto, no quiero agregar esto a React DnD.

Es fácil de implementar en el área del usuario y podrá hacer cosas como acelerar las llamadas getBoundingClientRect o poner el código de desplazamiento relacionado en un cuadro de animación.

Estoy dispuesto a agregar "desplazarse al pasar el mouse en la parte inferior" _como ejemplo_ a la prueba de esfuerzo ordenable . Esto implicaría agregar otro destino de colocación en el nivel del contenedor que solo escucha hover y se desplaza dentro de un cuadro de animación.

Sin embargo, no agregaré los métodos de coordenadas DOM a React DnD por las razones descritas anteriormente.

@gaearon Estoy interesado en una solución generalizada. ¿Cómo podemos usar react-dnd-html5-backend lugar de getBoundingClientRect directamente?

Resolví esto pasando las funciones DropTargetMonitor getInitialSourceClientOffset y getSourceClientOffset a una función de devolución de llamada dentro de mi evento onDrop . De esta manera, mi función de devolución de llamada puede calcular las coordenadas correctas relacionadas con el puerto de visualización.

// 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 no funciona con el componente funcional, y useDrop#drop no pasa ningún component in. Ahora, si quiero obtener el ref de mi componente, tengo para almacenarlo por separado y llamar manualmente al conector de caída para pasarlo. ¿Hay alguna forma más concisa de hacer esto?

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 , ¿tiene alguna muestra de código completa que estaría dispuesto a compartir, por favor?

@dendrocronología

Un ejemplo artificial: https://codesandbox.io/s/elastic-liskov-00ldf

La API es mejor cuando no tenemos que almacenar el ref nosotros mismos ( useGlobalDrop vs useLocalDrop ). Ahora, si solo el ref , que supongo que react-dnd ya obtiene, se adjunta ~ al objeto monitor ~ en algún lugar (accesible en drop , no tengo opinión donde), resolvería esto.

esta solución no es confiable, especialmente cuando hace zoom en el navegador o cambia la resolución del dispositivo. ¿alguna idea?

tengo la misma pregunta @ sepehr09

Pasando después de algunas búsquedas en Google ... ¿Alguna actualización sobre la pregunta original? (obteniendo el x / y de un elemento caído en relación con el objetivo de caída)

Supongo que me uniré a la lista de aquellos que necesitan esto. ¿Alguna ayuda por favor?

Creo que esta característica es muy necesaria, debe agregarse en la biblioteca. En este momento, cualquiera que haya trabajado con él, ¡ayúdenos!

¿Fue útil esta página
0 / 5 - 0 calificaciones