Tutorial

Como criar elementos de arrastar e soltar com JavaScript e HTML genéricos

Published on November 16, 2020
authorauthor

Jess Mitchell and Bradley Kouchi

Português
Como criar elementos de arrastar e soltar com JavaScript e HTML genéricos

Introdução

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.

Pré-requisitos

Para completar este tutorial, você precisará de:

  • Um navegador Web moderno que suporta a API de arrastar e soltar (Chrome 4+, Firefox 3.5+, Safari 3.1+, Edge 18+).

Passo 1 — Criando o projeto e a marcação inicial

Nosso projeto consistirá de um contêiner com dois tipos de elementos filhos:

  • Elementos filhos que você pode arrastar
  • Elementos filhos que podem ter elementos soltos neles

Primeiro, abra sua janela de terminal e crie um novo diretório de projeto:

  1. mkdir drag-and-drop-example

Em seguida, navegue até esse diretório:

  1. cd drag-and-drop-example

Em seguida, crie um arquivo index.html nesse diretório:

  1. nano index.html

Depois disso, adicione o código boilerplate para uma página em HTML:

index.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):

index.html
<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:

  1. nano style.css

A seguir, adicione estilos para os elementos em nosso arquivo index.html:

style.css
.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.

Captura de tela das divs draggable e dropzone

Em seguida, tornaremos a primeira <div> arrastável adicionando o atributo draggable:

index.html
<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.

Passo 2 — Manipulando eventos de arrastar e soltar com JavaScript

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:

index.html
<body>
  ...
  <script src="script.js"></script>
</body>

Em seguida, crie um novo arquivo script.js:

  1. 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:

  • uma string que declara o formato do segundo parâmetro
  • os dados reais sendo transferidos

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:

script.js
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:

script.js
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:

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:

Gif animado mostrando um elemento sendo arrastado, mas não sendo solto

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:

script.js
function onDragOver(event) {
  event.preventDefault();
}

Agora, adicionaremos ondragover ao nosso elemento dropzone em index.html:

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:

script.js
function onDrop(event) {
  const id = event
    .dataTransfer
    .getData('text');
}

Selecione nosso elemento draggable com a id que recuperamos:

script.js
function onDrop(event) {
  // ...

  const draggableElement = document.getElementById(id);
}

Selecione nosso elemento dropzone:

script.js
function onDrop(event) {
  // ...

  const dropzone = event.target;
}

Acrescente nosso elemento draggable ao menu dropzone:

script.js
function onDrop(event) {
  // ...

  dropzone.appendChild(draggableElement);
}

Reinicie nosso objeto dataTransfer:

script.js
function onDrop(event) {
  // ...

  event
    .dataTransfer
    .clearData();
}

Agora, adicionaremos ondrop ao nosso elemento dropzone em index.html:

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.

Gif animado mostrando um elemento sendo arrastado e solto em um alvo de soltar

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.

Passo 3 — Construindo um exemplo avançado com vários itens arrastáveis

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".

Gif animado mostrando várias tarefas sendo arrastadas e soltas em uma coluna Done

Para criar sua própria lista de tarefas, adicione mais elementos arrastáveis com ids únicas ao index.html:

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.

Conclusão

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.

Learn more about our products

About the authors
Default avatar
Jess Mitchell

author



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


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!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Featured on Community

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more