javascript css drag-and-drop

javascript - Toda la página como zona de arrastre para arrastrar y soltar



css drag-and-drop (1)

El truco consiste en utilizar una zona de colocación que cubra toda la página y almacenar en caché el target de window.ondragenter para comparar con el target de window.ondragleave .

Primero, la zona de caída:

<style> div.dropzone { /* positions to point 0,0 - required for z-index */ position: fixed; top: 0; left: 0; /* above all elements, even if z-index is used elsewhere it can be lowered as needed, but this value surpasses all elements when used on YouTube for example. */ z-index: 9999999999; /* takes up 100% of page */ width: 100%; height: 100%; /* dim the page with 50% black background when visible */ background-color: rgba(0,0,0,0.5); /* a nice fade effect, visibility toggles after 175ms, opacity will animate for 175ms. note display:none cannot be animated. */ transition: visibility 175ms, opacity 175ms; } </style> <!-- both visibility:hidden and display:none can be used, but the former can be used in CSS animations --> <div style="visibility:hidden; opacity:0" class="dropzone"></div>

A pesar de que la zona de colocación cubrirá toda la página, se utilizará visibility:hidden o display:none ocultará de la vista. Utilicé la visibility:hidden para que las animaciones CSS puedan usarse para animar la transición.

Asignando los eventos.

<script> /* lastTarget is set first on dragenter, then compared with during dragleave. */ var lastTarget = null; window.addEventListener("dragenter", function(e) { lastTarget = e.target; // cache the last target here // unhide our dropzone overlay document.querySelector(".dropzone").style.visibility = ""; document.querySelector(".dropzone").style.opacity = 1; }); window.addEventListener("dragleave", function(e) { // this is the magic part. when leaving the window, // e.target happens to be exactly what we want: what we cached // at the start, the dropzone we dragged into. // so..if dragleave target matches our cache, we hide the dropzone. if(e.target === lastTarget || e.target === document) { document.querySelector(".dropzone").style.visibility = "hidden"; document.querySelector(".dropzone").style.opacity = 0; } }); </script>

Así que aquí está el proceso: arrastra un archivo sobre la ventana y window.ondragenter se dispara inmediatamente. El target se establece en el elemento raíz, <html> . Entonces, inmediatamente se muestra su zona de caída, que cubre toda la página. window.ondragenter se disparará de nuevo, esta vez el objetivo será tu zona de caída. Cada vez que se dragenter evento dragenter , almacenará en caché el objetivo, ya que este será el objetivo que coincidirá con el último evento window.ondragleave que se dispara cuando se arrastra fuera de la ventana.

¿Por qué funciona esto? No tengo idea, pero así es como se hace. Este es prácticamente el único método de trabajo que se activa cuando el usuario arrastra la página.

Creo que funciona porque una vez que la zona de caída no está oculta, siempre será el último objetivo. Cubre cada píxel de la página, incluso la etiqueta <html> . Este método se basa en la activación de hojas de arrastre al salir de la ventana. Desafortunadamente, hay un error en Firefox que impide que funcione correctamente. Por favor, vote por él para que se arregle más pronto . A partir de Firefox 57.0.2, el dragleave parece disparar correctamente. Sin embargo, se requiere una solución, verificando el document lugar del elemento en caché:

if(e.target === lastTarget || e.target === document)

Aquí hay un JSBin de eso en acción . Probado en las últimas versiones de Chrome, Firefox, Edge e IE11.

Mientras escribía aplicaciones web que tomaban entrada de archivos, quería usar arrastrar y soltar, pero no quería solo una pequeña zona de descarga en la página. Pensé que sería más conveniente si pudiera dejarlo en cualquier lugar de la página. Afortunadamente, el evento window.ondrop se dispara en cualquier lugar de la página, pero quería un efecto elegante para mostrar al usuario visualmente que era posible arrastrar y soltar.

Para hacerlo, todo lo que se necesitaba era detectar cuándo se arrastraba un archivo a la ventana , y cuando se arrastraba , para activar un efecto que mostraba al usuario que la aplicación estaba habilitada para arrastrar. Resulta que los eventos de arrastre no son tan convenientes. Supuse que window.ondragenter solo se activaría una vez, cuando el usuario ingresara a la página. Luego, cuando dejaste la ventana, window.ondragleave la ventana. Incorrecto. Se dispara constantemente a medida que el mouse se mueve sobre elementos secundarios en la página.

Miré qué propiedades estaban disponibles en el objeto de evento, tratando de encontrar algo que pudiera aislar lo que necesitaba, pero nada funcionó. Lo más que conseguí fue poder cambiar el color de fondo del body . Y solo si no había nada más en la página.

Toneladas de sitios de carga de archivos lo hicieron bien. Imgur y WeTransfer, por ejemplo. Sus sitios estaban todos codificados en spahetti y comprimidos hasta el punto de la ilegibilidad, y no pude encontrar nada sobre el tema buscando en Google.

Entonces, ¿cómo se puede hacer esto?