Arrastrar y soltar JavaScript para dispositivos táctiles [cerrado]


120

Estoy buscando un complemento drag & DROP que funcione en dispositivos táctiles.

Me gustaría una funcionalidad similar al complemento jQuery UI que permite elementos "soltables".

El complemento jqtouch admite arrastrar, pero no soltar.

aquí está la función de arrastrar y soltar que solo es compatible con iPhone / iPad.

¿Alguien puede indicarme la dirección de un complemento de arrastrar y soltar que funciona en Android / iOS?

... O podría ser posible actualizar el complemento jqtouch para que se pueda soltar, ya se ejecuta en Andriod e IOS.

¡Gracias!


1
Esto está en progreso, pero no sé qué dispositivos lo admiten: Este plugins.jquery.com/project/mobiledraganddrop ... ¿ha revisado las bibliotecas de jQuerymobile.com? También encontré esta pregunta SO duplicada: stackoverflow.com/questions/3172100/…
iivel

Gracias. Sí, mobiledraganddrop solo admite hacer clic y soltar en dispositivos móviles. No pude encontrar nada en jQuerymobile.com. La otra pregunta ya tiene una respuesta marcada como correcta que se refiere a sencha.com/products/touch, que tiene una licencia de fuente limitada.
joe

Tengo curiosidad por uno que funcione en navegadores móviles y de escritorio.
Lime

Respuestas:


258

Puede usar la interfaz de usuario de Jquery para arrastrar y soltar con una biblioteca adicional que traduce los eventos del mouse al tacto, que es lo que necesita, la biblioteca que recomiendo es https://github.com/furf/jquery-ui-touch-punch , con esto, su arrastrar y soltar desde Jquery UI debería funcionar en dispositivos táctiles

o puede usar este código que estoy usando, también convierte los eventos del mouse en táctiles y funciona como magia.

function touchHandler(event) {
    var touch = event.changedTouches[0];

    var simulatedEvent = document.createEvent("MouseEvent");
        simulatedEvent.initMouseEvent({
        touchstart: "mousedown",
        touchmove: "mousemove",
        touchend: "mouseup"
    }[event.type], true, true, window, 1,
        touch.screenX, touch.screenY,
        touch.clientX, touch.clientY, false,
        false, false, false, 0, null);

    touch.target.dispatchEvent(simulatedEvent);
    event.preventDefault();
}

function init() {
    document.addEventListener("touchstart", touchHandler, true);
    document.addEventListener("touchmove", touchHandler, true);
    document.addEventListener("touchend", touchHandler, true);
    document.addEventListener("touchcancel", touchHandler, true);
}

Y en su documento, listo, simplemente llame a la función init ()

código encontrado desde aquí


11
Gracias, en mi dispositivo Android, las cosas ahora se pueden arrastrar. Sin embargo, el evento de clic ya no se activa cuando hago clic en él. ¿Hay alguna idea de cómo arreglar eso?
John Landheer

9
Nota: Dado que el detector de eventos está registrado para todo el documento, esta solución también deshabilita el desplazamiento en mi Nexus S ...
Ethan Leroy

29
Gracias por compartir esto. Sin embargo, debe dar crédito al autor original del código que ha publicado. ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript
undefined

2
@JohnLandheer Solucioné el problema adjuntando los oyentes de eventos solo a los objetos que quería arrastrar,document.getElementById('draggableContainer').addEventListener(...
chiliNUT

1
Touch-punch es genial. Una de esas cosas de 'simplemente funciona'. Por desgracia, no es compatible con el doble toque ... que me encantaría ver.
DA.

21

Para cualquiera que busque usar esto y mantener la funcionalidad de 'clic' (como menciona John Landheer en su comentario), puede hacerlo con solo un par de modificaciones:

Agregue un par de globales:

var clickms = 100;
var lastTouchDown = -1;

Luego modifique la declaración de cambio del original a esto:

var d = new Date();
switch(event.type)
{
    case "touchstart": type = "mousedown"; lastTouchDown = d.getTime(); break;
    case "touchmove": type="mousemove"; lastTouchDown = -1; break;        
    case "touchend": if(lastTouchDown > -1 && (d.getTime() - lastTouchDown) < clickms){lastTouchDown = -1; type="click"; break;} type="mouseup"; break;
    default: return;
}

Es posible que desee ajustar los 'clickms' a sus gustos. Básicamente, se trata de observar un 'inicio táctil' seguido rápidamente de un 'toque final' para simular un clic.


@EZ Hart: ¿podría decirme dónde poner su código en el código anterior para habilitar el evento de clic?
Valay

1
@ChakoDesai: el código de la respuesta se ha editado en gran medida desde que escribí mi respuesta. Visite stackoverflow.com/posts/6362527/revisions y mire el código del 30 de junio de 2011; mi respuesta tendrá mucho más sentido según esa versión.
EZ Hart

@EZ Hart: he actualizado mi código desde la URL proporcionada. Pero, ¿por qué a veces clickfunciona y a veces no?
Valay

@ChakoDesai - Sin ver tu código, no puedo estar seguro. Es posible que desee abrir una nueva pregunta para eso.
EZ Hart

Puede encontrar una respuesta actualizada para hacer que el código anterior funcione con eventos de clic aquí: stackoverflow.com/questions/28218888/…
Blunderfest

12

¡Gracias por los códigos anteriores! - Probé varias opciones y este fue el boleto. Tuve problemas porque preventDefault impedía el desplazamiento en el ipad; ahora estoy probando elementos que se pueden arrastrar y funciona muy bien hasta ahora.

if (event.target.id == 'draggable_item' ) {
    event.preventDefault();
}

¿Ha probado esto en Windows Phone? ¿O algo más que iPhone? Por experiencias pasadas, esto parece funcionar perfectamente en iPhones / iPads, pero no funciona bien en otros dispositivos, especialmente en Windows Phones.
casi un principiante

10

Tenía la misma solución que la respuesta de gregpress , pero mis elementos arrastrables usaban una clase en lugar de una identificación. Parece funcionar.

var $target = $(event.target);  
if( $target.hasClass('draggable') ) {  
    event.preventDefault();  
}

4
El hecho de que simplemente haya usado un selector diferente no garantiza que sea una respuesta separada, sino que debería haber comentado la respuesta de @ gregpress.
bPratik

2
@bPratik a menos que quisiera el formato más agradable que proporciona una respuesta, y el hecho de que proporcionó un ejemplo de código completo garantiza una respuesta separada. Sin embargo, debería haber dejado un comentario con un enlace a su respuesta ...
drzaus

8

Viejo hilo lo sé .......

El problema con la respuesta de @ryuutatsuo es que también bloquea cualquier entrada u otro elemento que tenga que reaccionar a los 'clics' (por ejemplo, entradas), así que escribí esta solución. Esta solución hizo posible utilizar cualquier biblioteca de arrastrar y soltar existente que se basa en eventos de mousedown, mousemove y mouseup en cualquier dispositivo táctil (o cumputer). Esta es también una solución para varios navegadores.

He probado en varios dispositivos y funciona rápido (en combinación con la función de arrastrar y soltar de ThreeDubMedia (ver también http://threedubmedia.com/code/event/drag )). Es una solución de jQuery, por lo que solo puede usarla con las bibliotecas de jQuery. He usado jQuery 1.5.1 porque algunas funciones más nuevas no funcionan correctamente con IE9 y superior (no probado con versiones más nuevas de jQuery).

Antes de agregar cualquier operación de arrastrar o soltar a un evento , primero debe llamar a esta función :

simulateTouchEvents(<object>);

También puede bloquear todos los componentes / elementos secundarios para la entrada o para acelerar el manejo de eventos utilizando la siguiente sintaxis:

simulateTouchEvents(<object>, true); // ignore events on childs

Aquí está el código que escribí. Usé algunos buenos trucos para acelerar la evaluación de las cosas (ver código).

function simulateTouchEvents(oo,bIgnoreChilds)
{
 if( !$(oo)[0] )
  { return false; }

 if( !window.__touchTypes )
 {
   window.__touchTypes  = {touchstart:'mousedown',touchmove:'mousemove',touchend:'mouseup'};
   window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,'input':1,'textarea':1,'select':1,'option':1};
 }

$(oo).bind('touchstart touchmove touchend', function(ev)
{
    var bSame = (ev.target == this);
    if( bIgnoreChilds && !bSame )
     { return; }

    var b = (!bSame && ev.target.__ajqmeclk), // Get if object is already tested or input type
        e = ev.originalEvent;
    if( b === true || !e.touches || e.touches.length > 1 || !window.__touchTypes[e.type]  )
     { return; } //allow multi-touch gestures to work

    var oEv = ( !bSame && typeof b != 'boolean')?$(ev.target).data('events'):false,
        b = (!bSame)?(ev.target.__ajqmeclk = oEv?(oEv['click'] || oEv['mousedown'] || oEv['mouseup'] || oEv['mousemove']):false ):false;

    if( b || window.__touchInputs[ev.target.tagName] )
     { return; } //allow default clicks to work (and on inputs)

    // https://developer.mozilla.org/en/DOM/event.initMouseEvent for API
    var touch = e.changedTouches[0], newEvent = document.createEvent("MouseEvent");
    newEvent.initMouseEvent(window.__touchTypes[e.type], true, true, window, 1,
            touch.screenX, touch.screenY,
            touch.clientX, touch.clientY, false,
            false, false, false, 0, null);

    touch.target.dispatchEvent(newEvent);
    e.preventDefault();
    ev.stopImmediatePropagation();
    ev.stopPropagation();
    ev.preventDefault();
});
 return true;
}; 

Qué hace: al principio, traduce eventos de un solo toque en eventos de mouse. Comprueba si un evento es causado por un elemento en / en el elemento que debe ser arrastrado. Si es un elemento de entrada como input, textarea, etc., omite la traducción, o si se le adjunta un evento de mouse estándar, también omitirá una traducción.

Resultado: todos los elementos de un elemento arrastrable siguen funcionando.

Feliz codificación, saludos, Erwin Haantjes


¿Qué objeto debo pasar simulateTouchEvents(<object>, true);?
Valay

Por ejemplo: simulateTouchEvents ($ ('# yourid;), true); o simulateTouchEvents (document.getElementById ('yourid'), verdadero); etc
Codebeat

¿Podrías mirar mi enlace de otra pregunta ?
Valay

Utilice threedubmedia.com/code/event/drag y desactive el movimiento xoy del elemento. Cuando utiliza el código de este artículo, puede "desplazar" las barras de desplazamiento. Pero sepa por qué quiere hacer esto porque una página en el teléfono móvil ya tiene barras de desplazamiento. No entiendo lo que quiere hacer con él. ¡Éxito!
Codebeat

Tengo que agregar arrastrar y soltar columnas y desplazar ambas. Cuando enciendo toucheventos chrome, no puedo desplazarme por la tabla. Ni siquiera en el móvil.
Valay
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.