Arrastar e Soltar com a Drag and Drop API em JavaScript
A Drag-and-Drop API permite que elementos sejam arrastados com o mouse e posicionados em locais específicos em uma página web. Durante o processo, identificamos dois elementos principais:
- Fonte do arrasto: o elemento que está sendo arrastado.
- Alvo do arrasto: o elemento ou área onde o item será solto.
Para tornar um elemento arrastável, basta adicionar o atributo draggable
com o valor true
. Qualquer elemento na página pode se tornar arrastável. Veja o exemplo abaixo:
<div style="width:50px; height:50px; background-color: red;" draggable="true"></div>
Por padrão, os elementos HTML não são arrastáveis. Já o alvo do arrasto pode ser qualquer elemento HTML configurado para receber os eventos apropriados.
Eventos do Drag-and-Drop
Ao arrastar e soltar um elemento, diversos eventos são disparados em diferentes momentos:
dragstart
: disparado quando o arrasto começa.drag
: disparado continuamente enquanto o elemento está sendo arrastado.dragend
: disparado quando o arrasto termina.dragenter
: disparado quando o elemento entra na área do alvo.dragover
: disparado continuamente enquanto o elemento está sobre o alvo.dragleave
: disparado quando o elemento sai do alvo.drop
: disparado quando o elemento é solto no alvo.
Esses eventos recebem um objeto DragEvent
como parâmetro, que herda propriedades dos objetos MouseEvent
e Event
.
O exemplo a seguir define um elemento arrastável e registra eventos para capturar as ações de arrasto e soltura.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Exemplo Drag-and-Drop</title>
<style>
#source {
width: 50px;
height: 50px;
background-color: red;
display: inline-block;
}
#target {
width: 200px;
height: 150px;
overflow: hidden;
border: #ccc 1px dashed;
}
div {
margin: 5px;
}
</style>
</head>
<body>
<div id="source" draggable="true"></div>
<div id="target"></div>
<script>
const source = document.getElementById("source");
source.addEventListener("dragstart", () => console.log("Arrasto iniciado"));
const target = document.getElementById("target");
target.addEventListener("dragover", (event) => {
event.preventDefault();
console.log("Elemento sobre o alvo");
});
target.addEventListener("drop", () => console.log("Elemento solto"));
</script>
</body>
</html>
Nesse exemplo:
dragstart
é disparado ao iniciar o arrasto do elementosource
.dragover
é disparado enquanto o elemento source está sobre o alvotarget
. O métodopreventDefault()
é chamado para habilitar soltar o elemento no alvo.drop
é disparado ao soltar o elemento no alvo.
No próximo exemplo, uma cópia do elemento arrastado é adicionada ao alvo.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Exemplo Drag-and-Drop</title>
<style>
#source {
width: 50px;
height: 50px;
background-color: red;
display: inline-block;
}
#target {
width: 200px;
height: 150px;
overflow: hidden;
border: #ccc 1px dashed;
}
div {
margin: 5px;
}
</style>
</head>
<body>
<div id="source" draggable="true"></div>
<div id="target"></div>
<script>
let dragged = null;
const source = document.getElementById("source");
source.addEventListener("dragstart", (e) => (dragged = e.target));
const target = document.getElementById("target");
target.addEventListener("dragover", (e) => e.preventDefault());
target.addEventListener("drop", (e) => e.target.appendChild(dragged.cloneNode(true)));
</script>
</body>
</html>
Neste exemplo:
- A referência ao elemento arrastado é armazenada na variável
dragged
durante odragstart
. - No evento
drop
, uma cópia do elemento original é criada usandocloneNode(true)
e adicionada aotarget
.
O resultado de adicionar cópias do elemento arrastado ao alvo é mostrado na imagem a seguir.
O exemplo a seguir mostra como mover o elemento original para o alvo, em vez de criar uma cópia.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Exemplo Drag-and-Drop</title>
<style>
#container {
width: 60px;
height: 60px;
}
#source {
width: 50px;
height: 50px;
background-color: red;
display: inline-block;
}
#target {
width: 200px;
height: 150px;
overflow: hidden;
border: #ccc 1px dashed;
}
div {
margin: 5px;
}
</style>
</head>
<body>
<div id="container"><div id="source" draggable="true"></div></div>
<div id="target"></div>
<script>
let dragged = null;
const source = document.getElementById("source");
source.addEventListener("dragstart", (e) => (dragged = e.target));
const target = document.getElementById("target");
target.addEventListener("dragover", (e) => e.preventDefault());
target.addEventListener("drop", (e) => {
dragged.parentNode.removeChild(dragged);
e.target.appendChild(dragged);
});
</script>
</body>
</html>
O resutado de mover o elemento arrastado para o alvo é mostrado na imagem a seguir.
Documentação oficial: