Solitario: Drag and Drop en JavaScript

Juan Mellado, 7 Febrero, 2006 - 20:21

He sacado un poco de tiempo para seguir con el juego del Solitario que estoy haciendo en JavaScript. Y he aprovechado para añadirle el efecto de drag and drop, para mover las cartas de un montón a otro, procurando ser fiel al funcionamiento del juego original.

Todo el control se hace por código, procesando los eventos de ratón adecuados para capturar el momento en que se pincha sobre una carta y se arrastra hasta liberarla. Aunque aún me queda por hacer todo el proceso de mover una pila de cartas a un mismo tiempo en vez de una sola carta.

Lo primero que he hecho ha sido definir tres variables en las que recoger el objeto sobre el que se ha pinchado y las coordernadas X e Y relativas al objeto sobre las que se ha pinchado:

var drag = null;
var dragX = 0, dragY = 0;

Y a continuación he capturado los tres eventos de ratón oportunos:

function registerMouse() {
  document.onmousedown = onMouseDown;
  document.onmousemove = onMouseMove;
  document.onmouseup   = onMouseUp;
}

En el primer evento se comprueba al pinchar sobre un objeto HTML si es una carta mirando si su clase CSS es "card", y si lo es se inicializan las tres variables definidas anteriormente:

function onMouseDown(e) {
  var object = getMouseObject(e);
  if (object.className == "card") {
    drag  = object;
    dragX = pxToNumber(drag.style.left) - getMouseX(e);
    dragY = pxToNumber(drag.style.top)  - getMouseY(e);
    return(false);
  }
}

En el segundo evento se mueve el objeto siendo arrastrado actualizando sus coordenadas. Curiosamente, lo más importante aquí es el "return(false)", si no se pone entonces el código no funciona correctamente. Me ha dado bastantes quebraderos de cabeza hasta que me he dado cuenta.

function onMouseMove(e) {
  if (drag) {
    drag.style.left = String(dragX + getMouseX(e) ) + "px";
    drag.style.top  = String(dragY + getMouseY(e) ) + "px";
    return(false);
  }
}

La última función se limita a liberar la referencia al objeto siendo arrastrado:

function onMouseUp(e) {
  drag = null;
}

Para evitar la dependencias, y hacer que el código funcionara bien en Firefox e Internet Explorer, he creado una serie de funciones auxiliares que extraen los valores correctos de los eventos según el navegador:

function getMouseObject(e) {
  return(e? e.target: window.event.srcElement);
}

function getMouseX(e) {
  return(e? e.clientX: window.event.clientX);
}

function getMouseY(e) {
  return(e? e.clientY: window.event.clientY);
}

function pxToNumber(s) {
  return( Number( s.substring(0, s.length - 2) ) );
}

¿No encontró lo que buscaba?

Utilice el buscador para encontrar más páginas en esta web o en toda Internet.
 
Web www.inmensia.com
frandy (no verificado), 9 Agosto, 2007 - 23:43

Me parece interesante, pero no veo un enlace a una pagina de prueba, un demo del funcionamiento. O bueno, al menos un ejemplo de como ponerlo a funcionar.

Saludos.

Juan Carlos Guillén Zurita (no verificado), 21 Agosto, 2007 - 17:06

Excellent!!!

bluejc (no verificado), 25 Enero, 2008 - 03:28

A mi no me funcionó hasta que le inserte un drag.style.position="absolute" en el onMouseMove o también poniendolo en el style del elemento a mover style="position:absolute"

Saludos
bluejc