Restaurar correctamente un elemento arrastrable a su posición de inicio

Estoy usando InteractJs library en una aplicación Rails 6. He implementado los eventos de arrastrar y soltar.
La funcionalidad de arrastrar y soltar funciona bien. El problema que estoy enfrentando es si dejo un elemento fuera de la zona de gota y lo coloco a su posición original, se coloca allí, pero si intento arrastrar ese elemento de nuevo aparece en la posición donde terminó el arrastramiento anterior y no donde fue restaurado, este es el problema que estoy buscando resolver

A continuación está mi código para los eventos

var dragMoveListener = function (event) {
  var target, x, y;
  target = event.target;
  x = (parseFloat(target.getAttribute("data-x")) || 0) + event.dx;
  y = (parseFloat(target.getAttribute("data-y")) || 0) + event.dy;
  target.style.webkitTransform = target.style.transform =
    "translate(" + x + "px, " + y + "px)";
  target.setAttribute("data-x", x);
  return target.setAttribute("data-y", y);
};

window.dragMoveListener = dragMoveListener;

interact('*[data-draggable="true"]').draggable({
  inertia: false,
  autoScroll: true,
  onmove: dragMoveListener,
});

const restoreToOriginalPosition = (event) => {
  // this restores the element to it's original position but the next time I attempt to drag it, it appears on the position where the previous dragging ended
  event.relatedTarget.style.transform = "translate(0px, 0px)";
};

$(document).on("turbolinks:load", function () {
  interact("#dropzone").dropzone({
    accept: '*[data-draggable="true"]',
    overlap: 0.75,

    ondropactivate: function (event) {
      // ...
    },

    ondrop: function (event) {
      const product_id = event.relatedTarget.attributes["data-product-id"].value;
      // my use case is to remove the element from DOM if it's dropped into the dropzone, otherwise restore to it's starting position
      $(event.relatedTarget).remove();
      addToCart(product_id); //it's definition is not relevant here
    },

    ondropdeactivate: function (event) {
      restoreToOriginalPosition(event);
    },
  });
});

En el ondrop oyente del evento He intentado restaurar el elemento a su posición original en la página. Ver la función restoreToOriginalPosition que pone con éxito el elemento a su posición original.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por syntaxsculptor


3 Respuestas:

  • Tuve que quitar/reestablecer data-x y data-y atributos de los draggable elemento.

    const restoreToOriginalPosition = (event) => {
      event.relatedTarget.removeAttribute("data-x");
      event.relatedTarget.removeAttribute("data-y");
      event.relatedTarget.style.transform = "translate(0px, 0px)";
    };
    

    Esto solucionó el problema.

    Respondida el Dec 16, 2020 a las 20:05 - por devguru123

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando es debido a que, al restaurar el elemento a su posición original en el ondropdeactivate event listener, estás modificando directamente la propiedad transform del elemento en el DOM. Sin embargo, al hacer esto, InteractJS no actualiza internamente la propiedad data-x y data-y que utiliza para llevar el seguimiento de la posición del elemento draggeable.

    Para solucionar esto y restaurar correctamente un elemento arrastrable a su posición de inicio, deberías actualizar también las propiedades data-x y data-y cuando estás restaurando el elemento a su posición original. Aquí te dejo una modificación en tu código para lograr esto:

    javascript
    const restoreToOriginalPosition = (event) => {
      event.relatedTarget.style.transform = "translate(0px, 0px)";
      event.relatedTarget.setAttribute("data-x", 0);
      event.relatedTarget.setAttribute("data-y", 0);
    };
    

    Al agregar estas líneas en la función restoreToOriginalPosition, te asegurarás de que cuando restaures el elemento a su posición original, también actualices las propiedades data-x y data-y, de manera que InteractJS pueda seguir la nueva posición correctamente cuando se intente arrastrar nuevamente el elemento.

    Con esta modificación, el elemento debería ser restaurado a su posición de inicio y no aparecer en la posición donde terminó el arrastramiento anterior la próxima vez que se intente arrastrar.

    Respondida el Dec 17, 2020 a las 20:05 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema es que estás usando event.relatedTarget para obtener el elemento que se soltó en la zona de caída. event.relatedTarget es el elemento que estaba bajo el cursor del mouse cuando se soltó el elemento, que no es necesariamente el elemento que se arrastró.

    Para obtener el elemento que se arrastró, debes usar event.target. Aquí tienes el código corregido:

    js
    const restoreToOriginalPosition = (event) => {
      // this restores the element to it's original position but the next time I attempt to drag it, it appears on the position where the previous dragging ended
      event.target.style.transform = "translate(0px, 0px)";
    };
    

    Además, asegúrate de que le has dado a cada elemento arrastrable un ID único. Esto es necesario para que Interact.js pueda rastrear correctamente los elementos mientras se arrastran.

    Respondida el Dec 17, 2020 a las 20:14 - por Gemini

    Votos positivos: 0 | Votos negativos: 0