Arrastar e soltar é uma interação comum presente em muitas interfaces gráficas de usuário.
Existem bibliotecas de JavaScript pré-existentes para adicionar um recurso de arrastar e soltar à sua aplicação. No entanto, pode haver situações em que uma biblioteca não está disponível ou introduz uma sobrecarga ou dependência que seu projeto não precisa. Nessas situações, o conhecimento das APIs disponíveis em navegadores Web modernos pode oferecer soluções alternativas para você.
A API HTML de arrastar e soltar depende do modelo de eventos do DOM para obter informações sobre o que está sendo arrastado ou solto e atualizar esse elemento. Com os manipuladores de eventos JavaScript, você pode transformar qualquer elemento em um item arrastável ou em um item no qual se possa soltar outro elemento.
Neste tutorial, vamos construir um exemplo de arrastar e soltar usando a API HTML com JavaScript genérico para isso. Desse modo, usaremos também os manipuladores de eventos.
Para completar este tutorial, você precisará de:
Nosso projeto consistirá de um contêiner com dois tipos de elementos filhos:
Primeiro, abra sua janela de terminal e crie um novo diretório de projeto:
- mkdir drag-and-drop-example
Em seguida, navegue até esse diretório:
- cd drag-and-drop-example
Em seguida, crie um arquivo index.html
nesse diretório:
- nano index.html
Depois disso, adicione o código boilerplate para uma página em HTML:
<!DOCTYPE html>
<html>
<head>
<title>My Drag-and-Drop Example</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
</body>
</html>
E, entre as tags <body>
, adicione seu item draggable
e sua dropzone
(destino para soltar):
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
>
draggable
</div>
</div>
<div
class="example-dropzone"
>
dropzone
</div>
</div>
Salve e feche o arquivo. Em seguida, crie um arquivo style.css
:
- nano style.css
A seguir, adicione estilos para os elementos em nosso arquivo index.html
:
.example-parent {
border: 2px solid #DFA612;
color: black;
display: flex;
font-family: sans-serif;
font-weight: bold;
}
.example-origin {
flex-basis: 100%;
flex-grow: 1;
padding: 10px;
}
.example-draggable {
background-color: #4AAE9B;
font-weight: normal;
margin-bottom: 10px;
margin-top: 10px;
padding: 10px;
}
.example-dropzone {
background-color: #6DB65B;
flex-basis: 100%;
flex-grow: 1;
padding: 10px;
}
Isso irá adicionar algumas formatações à aplicação. Agora, visualize o index.html
no navegador e observe que isso produz uma <div>
draggable
e uma <div>
dropzone
.
Em seguida, tornaremos a primeira <div>
arrastável adicionando o atributo draggable
:
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
draggable="true"
>
draggable
</div>
</div>
<div
class="example-dropzone"
>
dropzone
</div>
</div>
Salve e feche o arquivo.
Por fim, visualize o index.html
no navegador novamente. Se clicarmos na <div>
draggable
e a arrastarmos pela tela, deve haver uma indicação visual de sua movimentação.
O valor padrão para o atributo draggable
é auto
. Isso significa que o fato de o elemento ser arrastável será determinado pelo comportamento padrão do seu navegador. Normalmente, isso significa que seleções de texto, imagens e links são arrastáveis sem especificar draggable="true"
.
Agora, você tem um arquivo HTML com um elemento arrastável. Vamos prosseguir adicionando manipuladores onevent
.
Atualmente, se liberarmos o mouse enquanto arrastamos o elemento arrastável, nada acontece. Para disparar uma ação ao arrastar ou soltar nos elementos DOM, vamos precisar utilizar a API de arrastar e soltar:
ondragstart
: este manipulador de eventos será anexado ao nosso elemento draggable
e será disparado quando um evento dragstart
ocorrer.ondragover
: este manipulador de eventos será anexado ao nosso elemento dropzone
e será disparado quando um evento dragover
ocorrer.ondrop
: este manipulador de eventos será anexado ao nosso elemento dropzone
e será disparado quando um evento drop
ocorrer.Nota: existem oito manipuladores de eventos no total: ondrag
, ondragend
, ondragenter
, ondragexit
, ondragleave
ondragover
, ondragstart
e ondrop
. Para nosso exemplo, não vamos precisar de todos eles.
Primeiro, vamos fazer referência a um novo arquivo script.js
em nosso index.html
:
<body>
...
<script src="script.js"></script>
</body>
Em seguida, crie um novo arquivo script.js
:
- nano script.js
O objeto DataTransfer
irá manter o controle das informações relacionadas ao arrasto atual. Para atualizar nosso elemento em arrastar e soltar, precisamos acessar diretamente o objeto DataTransfer
. Para fazer isso, selecione a propriedade dataTransfer
do element DragEvent
do DOM.
Nota: o objeto DataTransfer
pode monitorar tecnicamente informações para vários elementos sendo arrastados ao mesmo tempo. Para o nosso exemplo, vamos focar em arrastar um elemento.
O método setData
do objeto dataTransfer
pode ser usado para definir as informações de estado de arrastar para seu elemento atualmente arrastado. Ele recebe dois parâmetros:
Nosso objetivo é mover o elemento draggable
para um novo elemento pai. Precisamos ser capazes de selecionar o elemento draggable
com uma id
única. Podemos definir a id
do elemento arrastado com o método setData
para que ela possa ser usada mais tarde.
Vamos revisitar nosso arquivo script.js
e criar uma nova função para usar setData
:
function onDragStart(event) {
event
.dataTransfer
.setData('text/plain', event.target.id);
}
Nota: o Internet Explorer 9 a 11 tem problemas com o uso de 'text/plain'
. O formato precisa ser 'text'
para esse navegador.
Para atualizar o estilo CSS do item arrastado, vamos acessar seus estilos usando o evento DOM novamente e definir quaisquer estilos que quisermos para o currentTarget
.
Vamos adicionar à nossa função e alterar o backgroundColor
para amarelo
:
function onDragStart(event) {
event
.dataTransfer
.setData('text/plain', event.target.id);
event
.currentTarget
.style
.backgroundColor = 'yellow';
}
Nota: quaisquer estilos que você alterar precisarão ser atualizados manualmente novamente ao soltar, caso você queira estilos somente de arrastar. Se você mudar alguma coisa quando começar a arrastar, o elemento arrastado irá manter esse novo estilo a menos que você o altere novamente.
Agora, temos nossa função JavaScript para quando começar a arrastar.
Adicionaremos ondragstart
ao elemento draggable
em index.html
:
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
draggable
</div>
</div>
<div class="example-dropzone">
dropzone
</div>
</div>
Visualize o index.html
em seu navegador. Se você tentar arrastar seu item agora, o estilo declarado em nossa função será aplicado:
No entanto, nada acontecerá quando você liberar seu clique.
O próximo manipulador de eventos disparado nesta sequência é ondragover
.
O comportamento padrão de soltar para certos elementos DOM como <div>
s em navegadores normalmente não aceita soltar. Esse comportamento irá interceptar o comportamento que estamos tentando implementar. Para garantir que obtemos o comportamento de soltar desejado, iremos aplicar preventDefault
.
Vamos revisitar nosso arquivo script.js
e criar uma nova função para usar preventDefault
. Adicione esse código ao final do arquivo:
function onDragOver(event) {
event.preventDefault();
}
Agora, adicionaremos ondragover
ao nosso elemento dropzone
em index.html
:
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
draggable
</div>
</div>
<div
class="example-dropzone"
ondragover="onDragOver(event);"
>
dropzone
</div>
</div>
Neste ponto, ainda não escrevemos o código para lidar com a soltura real. O manipulador de eventos final acionado nesta sequência é ondrop
.
Vamos revisitar nosso arquivo script.js
e criar uma nova função.
Podemos fazer referência aos dados que salvamos anteriormente com o método setData
do objeto dataTransfer
. Usaremos o método getData
do objeto dataTransfer
. O dado que definimos foi a id
. Assim, isso é o que será retornado a nós:
function onDrop(event) {
const id = event
.dataTransfer
.getData('text');
}
Selecione nosso elemento draggable
com a id
que recuperamos:
function onDrop(event) {
// ...
const draggableElement = document.getElementById(id);
}
Selecione nosso elemento dropzone
:
function onDrop(event) {
// ...
const dropzone = event.target;
}
Acrescente nosso elemento draggable
ao menu dropzone
:
function onDrop(event) {
// ...
dropzone.appendChild(draggableElement);
}
Reinicie nosso objeto dataTransfer
:
function onDrop(event) {
// ...
event
.dataTransfer
.clearData();
}
Agora, adicionaremos ondrop
ao nosso elemento dropzone
em index.html
:
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
draggable
</div>
</div>
<div
class="example-dropzone"
ondragover="onDragOver(event);"
ondrop="onDrop(event);"
>
dropzone
</div>
</div>
Feito isso, temos um recurso de arrastar e soltar completo. Visualize o index.html
em seu navegador e arraste o elemento draggable
para a dropzone
.
Nosso exemplo trata do cenário de um único item arrastável e um único alvo de soltar. Você pode ter vários itens arrastáveis, vários alvos de soltar e personalizá-los com todos os outros manipuladores de eventos da API de arrastar e soltar.
Aqui está mais um exemplo de como usar essa API: uma lista de tarefas com tarefas arrastáveis que você pode mover de uma coluna "To-do"
para uma coluna "Done"
.
Para criar sua própria lista de tarefas, adicione mais elementos arrastáveis com id
s únicas ao index.html
:
<div class="example-parent">
<h1>To-do list</h1>
<div class="example-origin">
To-do
<div
id="draggable-1"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
thing 1
</div>
<div
id="draggable-2"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
thing 2
</div>
<div
id="draggable-3"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
thing 3
</div>
<div
id="draggable-4"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
thing 4
</div>
</div>
<div
class="example-dropzone"
ondragover="onDragOver(event);"
ondrop="onDrop(event);"
>
Done
</div>
</div>
Visualize o index.html
em seu navegador e arraste os itens da coluna To-do para a coluna Done. Você criou uma aplicação de lista de tarefas e testou a funcionalidade.
Neste artigo, você criou uma aplicação de lista de tarefas para explorar a funcionalidade de arrastar e soltar que está disponível nos navegadores Web modernos.
A API de arrastar e soltar fornece várias opções para personalizar suas ações além de arrastar e soltar. Por exemplo, você pode atualizar o estilo CSS de seus itens arrastados. Além disso, em vez de mover o item, você pode optar por copiar seu item arrastável para que ele seja replicado ao soltar.
Tenha em mente que, embora muitos navegadores Web suportem essa tecnologia, pode ser que você não possa confiar nela se seu alvo for composto de dispositivos que não suportam essa funcionalidade.
Para aprender mais sobre tudo o que você pode soltar com a API de arrastar e soltar, confira a documentação da MDN nela.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!