javascript - Reencendido de eventos de puntero en la capa inferior(para arrastrar de forma irregular con interact.js)
jquery (2)
¿Ha intentado establecer los pointer-events: none
propiedad css pointer-events: none
en los niveles más altos (también se podría establecer a través de javascript)?
Necesito construir / disparar manualmente un evento de ratón de una manera que pueda ser manejado por cualquier controlador de eventos relevante (ya sea directamente en JS, jQuery o interact.js), como lo haría un evento natural de ratón de ratón. Sin embargo, el evento no parece desencadenar nada de la forma que yo esperaba.
Estoy tratando de hacer que algunas imágenes de forma irregular se puedan arrastrar usando la biblioteca interact.js. Las imágenes son simplemente img elementos rectangulares con porciones transparentes. En cada elemento, he definido 2 escuchas de eventos interact.js:
- Verificando si el clic estaba dentro del área de la imagen, deshabilitando el arrastre si no (se dispara en el evento "abajo")
- Manejando el arrastre (dispara en el evento "arrastre")
Sin embargo, si los elementos img se superponen y el usuario hace clic en el área transparente del elemento superior pero en el área rellena del elemento inferior, el elemento inferior debe ser el objetivo del arrastre. Después de probar varias cosas (ver más abajo), me decidí por la solución de: reordenar los índices z de los elementos al mismo tiempo que deshabilito la función de arrastrar en el paso 1, y luego relanzar el evento mousedown en todos los elementos inferiores . Estoy usando el tipo de evento "nativo" (no jQuery o interact.js) con la esperanza de que, literalmente, simplemente replique el evento original de mousedown.
// code to re-assign "zIndex"s
function demote(element, interactible, event){
// block dragging on element
interactible.draggable(false);
// get all images lower than the target
var z = element.css("zIndex");
var images = $("img").filter(function() {
return Number($(this).css("zIndex")) < z;
});
// push the target to the back
element.css("zIndex",1);
// re-process all lower events
$(images).each( function () {
// move element up
$(this).css("zIndex",Number($(this).css("zIndex"))+1);
// re-fire event if element began below current target
elem = document.getElementById($(this).attr(''id''));
// Create the event.
e = new MouseEvent("mousedown", {clientX: event.pageX, clientY: event.pageY});
var cancelled = !elem.dispatchEvent(e);
});
}
Desafortunadamente, esto no funciona, ya que el evento mousedown no se registra con ninguno de los manejadores. ¿Por qué?
Tengo todo el código (relevante) en este JSFiddle: https://jsfiddle.net/tfollo/xr27938a/10/ Tenga en cuenta que este JSFiddle no parece funcionar tan bien como lo hace en una ventana normal del navegador, pero creo que Demuestra la funcionalidad deseada.
Otras cosas que he probado:
Muchas personas han propuesto diferentes esquemas para manejar problemas similares (es decir, reenviar eventos a capas más bajas, usar eventos de puntero: ninguno, etc.), pero ninguno parece funcionar para activar el controlador interact.js y comenzar una interacción de arrastre en el elemento correcto . También intenté usar la interaccion.start (provista por interact.js) pero parece tener errores: hay al menos un problema abierto sobre el tema y cuando intenté iniciar una nueva interacción de arrastre en un objetivo de mi elección, obtuve muchos Errores desde dentro del código de la biblioteca.
No estoy en contra de volver a visitar ninguna de estas soluciones per se, pero también me gustaría saber por qué disparar manualmente un evento de mousedown no funciona.
La idea es escuchar down
evento en el elemento padre y elegir arrastrar objetivo manualmente. Tampoco usé el índice z para elegir qué imagen arrastrar, porque el índice z no funciona con la position:static
. En lugar de eso, solo le di prioridad a las imágenes, todo depende de ti. https://jsfiddle.net/yevt/6wb5oxx3/3/
var dragTarget;
function dragMoveListener (event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute(''data-x'')) || 0) + event.dx,
y = (parseFloat(target.getAttribute(''data-y'')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
''translate('' + x + ''px, '' + y + ''px)'';
// update the posiion attributes
target.setAttribute(''data-x'', x);
target.setAttribute(''data-y'', y);
}
function setDragTarget(event) {
//choose element to drag
dragTarget = $(''#parent'').find(''img'')
.filter(function(i, el) {
var clickCandicateRect = el.getBoundingClientRect();
return insideBoundingRect(event.x, event.y, clickCandicateRect);
}).sort(byPriority).get(0);
}
function insideBoundingRect(x, y, rect) {
return (rect.left <= x) && (rect.top <= y) && (rect.right >= x) && (rect.bottom >= y);
}
function byPriority (a, b) {
return $(b).data(''priority'') - $(a).data(''priority'');
}
function startDrag(event) {
var interaction = event.interaction;
var target = dragTarget;
if (!interaction.interacting()) {
interaction.start({ name: ''drag'' }, event.interactable, target);
}
}
//Give priority as you wish
$(''#face1'').data(''priority'', 2);
$(''#face2'').data(''priority'', 1);
interact(''#parent'').draggable({
//use manualStart to determine which element to drag
manualStart: true,
onmove: dragMoveListener,
restrict: {
restriction: "parent",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
})
.on(''down'', setDragTarget)
.on(''move'', startDrag);