Arrastar e soltar JavaScript

Resumo : neste tutorial, você aprenderá sobre a API JavaScript de arrastar e soltar e como usá-la para implementar um aplicativo simples de arrastar e soltar.

Introdução à API JavaScript Drag and Drop

HTML5 introduziu formalmente a especificação de arrastar e soltar. A maioria dos navegadores modernos implementou arrastar e soltar nativo com base nas especificações HTML5.

Por padrão, apenas imagens e texto podem ser arrastáveis. Para arrastar uma imagem, basta segurar o botão do mouse e movê-la. Para arrastar o texto, você precisa destacar algum texto e arrastá-lo da mesma forma que arrastaria uma imagem.

A especificação HTML5 especifica que quase todos os elementos podem ser arrastáveis. Para tornar um elemento arrastável, você adiciona a draggablepropriedade com o valor trueà sua tag HTML. Por exemplo:

<div class="item" draggable="true"></div>Linguagem de código:  HTML, XML  ( xml )

Eventos em elementos arrastáveis

Quando você arrasta um elemento, esses eventos são acionados na seguinte sequência:

  • dragstart
  • drag
  • dragend

Quando você segura o botão do mouse e começa a movê-lo, o dragstartevento é acionado no elemento arrastável que você está arrastando. O cursor muda para um símbolo de não soltar (um círculo com uma linha atravessando-o) para indicar que você não pode soltar o elemento sobre si mesmo.

Após o dragstartevento ser acionado, ele dragserá acionado repetidamente enquanto você arrastar o elemento.

E o dragendevento é acionado quando você para de arrastar o elemento.

O alvo de todos os eventos ( e.target) é o elemento que está sendo arrastado.

Por padrão, o navegador não altera a aparência do elemento arrastado. Portanto, você pode personalizar sua aparência com base em suas preferências.

Eventos em destinos de lançamento

Quando você arrasta um elemento sobre um destino de soltar válido, esses eventos são acionados na seguinte sequência:

  • dragenter
  • dragover
  • dragleaveoudrop

O dragenterevento é acionado assim que você arrasta o elemento sobre um destino para soltar.

Após o dragenterevento ser acionado, dragoverele será acionado repetidamente enquanto você arrastar o elemento dentro do limite do destino para soltar.

Quando você arrasta o elemento para fora do limite do destino de soltar, o dragoverevento para de ser acionado e o dragleaveevento é acionado.

Caso você solte o elemento no destino, o dropevento é acionado em vez do dragleaveevento.

O destino ( e.target) dos eventos dragenter, dragover, dragleavee dropsão os elementos de destino para soltar.

Destino de lançamento válido

Quase todos os elementos suportam os eventos de destino de descarte ( dragenter, dragover, dragleavee drop). No entanto, eles não permitem a eliminação por padrão.

Se você soltar um elemento sobre um destino de soltura que não permite a queda, o dropevento não será acionado.

Para transformar um elemento em um destino de descarte válido, você pode substituir o comportamento padrão de ambos dragenteros dragovereventos chamando o event.preventDefault()método em seus manipuladores de eventos correspondentes. (Veja a seção de exemplo para mais informações)

Transferir dados usando o objeto dataTransfer

Para transferir dados em uma ação de arrastar e soltar, você usa o dataTransferobjeto.

O dataTransferobjeto é uma propriedade do evento. Ele permite transferir dados do elemento arrastado para o destino de soltar.

O dataTransferobjeto possui dois métodos: setData()e getData().

O setData()permite definir os dados da operação de arrastar para o formato e dados especificados:

dataTransfer.setData(format, data)Linguagem de código:  CSS  ( css )

O formato pode ser text/plainou text/uri-list. E os dados podem ser uma string representando os dados a serem adicionados ao objeto de arrastar.

O getData()método recupera os dados de arrastar armazenados pelo setData()método.

O getData()aceita um argumento:

dataTransfer(format)

O formato pode ser text/plainou text/uri-list. O getData()retorna uma string armazenada pelo setData()método ou uma string vazia se a operação de arrastar não incluir dados.

Exemplo de arrastar e soltar JavaScript

Desenvolveremos o seguinte aplicativo simples de arrastar e soltar para demonstrar a API JavaScript de arrastar e soltar:

Crie a estrutura do projeto

Primeiro, crie uma nova pasta chamada drag-n-drop-basics. Dentro desta pasta, crie duas subpastas chamadas csse js.

Segundo, crie um novo arquivo chamado app.jsna jspasta, style.cssna csspasta e index.htmlna drag-n-drop-basicspasta.

Terceiro, coloque o link para a style.csstag de script e vinculada a app.jsno index.htmlarquivo assim:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript - Drag and Drop Demo</title>
    <link rel="stylesheet" href="css/style.css">
</head>

<body>
   
    <script src="js/app.js"></script>
</body>

</html>Linguagem de código:  HTML, XML  ( xml )

Para o CSS, você pode obtê-lo aqui .

Construa o arquivo index.html

Coloque o seguinte código no index.htmlarquivo:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript - Drag and Drop Demo</title>
    <link rel="stylesheet" href="css/style.css">
</head>

<body>
    <div class="container">
        <h1>JavaScript - Drag and Drop</h1>
        <div class="drop-targets">
            <div class="box">
                <div class="item" id="item">
                </div>
            </div>
            <div class="box"></div>
            <div class="box"></div>
        </div>
    </div>
    <script src="js/app.js"></script>
</body>

</html>Linguagem de código:  HTML, XML  ( xml )

Neste arquivo index.html, usamos o .containerelemento para alinhar o título e drop-targetso elemento.

Dentro do elemento drop-targets, colocamos três divelementos com a mesma classe box. E colocamos outro elemento div com a classe itemna primeira caixa.

Se você abrir index.htmle tentar arrastar a caixa amarela, verá o cursor indicando que não é possível arrastar:

Para tornar o elemento arrastável, adicione a draggablepropriedade com o valor de trueà sua tag HTML da seguinte maneira:

<div class="item" id="item" draggable="true">Linguagem de código:  JavaScript  ( javascript )

Agora, se você salvar o index.html, abri-lo novamente no navegador, você verá que pode arrastar o elemento item assim:

Lidar com eventos no elemento arrastável

O style.cssarquivo possui a .hideclasse que oculta um elemento:

.hide {
    display: none;
}Linguagem de código:  CSS  ( css )

No app.jsarquivo, você adiciona o seguinte código:

// select the item element
const item = document.querySelector('.item');

// attach the dragstart event handler
item.addEventListener('dragstart', dragStart);

// handle the dragstart

function dragStart(e) {
   console.log('drag starts...');
}
Linguagem de código:  JavaScript  ( javascript )

Como funciona:

  • Primeiro, selecione o elemento arrastável usando o arquivo querySelector().
  • Segundo, anexe um dragstartmanipulador de eventos ao elemento arrastável.
  • Terceiro, defina a dragStart()função para tratar o dragstartevento.

Se você abrir o arquivo index.html e começar a arrastar o elemento arrastável, verá a drag starts...mensagem no console.

No dragStartmanipulador de eventos, você precisa armazenar o idelemento arrastável. E você precisa esconder isso:

function dragStart(e) {
    e.dataTransfer.setData('text/plain', e.target.id);
    e.target.classList.add('hide');
}Linguagem de código:  JavaScript  ( javascript )

Se você arrastar o elemento, verá que ele desaparece assim que você começar a arrastar.

Para resolver isso, você usa a setTimeout()função:

function dragStart(e) {
    e.dataTransfer.setData('text/plain', e.target.id);
    setTimeout(() => {
        e.target.classList.add('hide');
    }, 0);

}Linguagem de código:  JavaScript  ( javascript )

Agora você pode arrastar o elemento arrastável para fora de sua posição original:

Lidar com eventos em destinos de descarte

O arquivo style.css também possui uma classe CSS chamada .drag-overque transforma o estilo da borda do destino para soltar em tracejado e vermelho:

.drag-over {
    border: dashed 3px red;
}
Linguagem de código:  CSS  ( css )

No app.js, você precisa selecionar os elementos de destino para soltar e manipular os eventos dragenter, dragover, dragleavee dropdesses elementos:

const boxes = document.querySelectorAll('.box');

boxes.forEach(box => {
    box.addEventListener('dragenter', dragEnter)
    box.addEventListener('dragover', dragOver);
    box.addEventListener('dragleave', dragLeave);
    box.addEventListener('drop', drop);
});

function dragEnter(e) {
}

function dragOver(e) {
}

function dragLeave(e) {
}

function drop(e) {
}
Linguagem de código:  JavaScript  ( javascript )

O estilo da borda do destino para soltar deve mudar quando o evento dragentere dragoverocorrer. Deve restaurar o estilo quando o evento dragleavee dropocorrer.

Para fazer isso, você adiciona e remove a drag-overclasse do dropdestino assim:

function dragEnter(e) {
    e.target.classList.add('drag-over');
}

function dragOver(e) {
    e.target.classList.add('drag-over');
}

function dragLeave(e) {
    e.target.classList.remove('drag-over');
}

function drop(e) {
    e.target.classList.remove('drag-over');

}Linguagem de código:  JavaScript  ( javascript )

Agora, se você arrastar o elemento arrastável para outro destino para soltar, verá que a borda do destino para soltar muda conforme mostrado na imagem a seguir:

Para tornar o destino de descarte válido, você precisa chamar event.preventDefault()os manipuladores de eventos dragentere dragovercomo este:

function dragEnter(e) {
    e.preventDefault();
    e.target.classList.add('drag-over');
}

function dragOver(e) {
    e.preventDefault();
    e.target.classList.add('drag-over');
}Linguagem de código:  JavaScript  ( javascript )

Se você não fizer isso, o dropevento nunca será acionado porque o divelemento não é um destino de descarte válido por padrão.

Se você arrastar o elemento arrastável para um destino para soltar, verá que o cursor muda indicando que você pode soltar o elemento:

Agora, se você descartar o elemento item, verá que ele desaparece imediatamente.

Para resolver esse problema, você precisa adicionar o identificador do dropevento.

  • Primeiro, obtenha o idelemento arrastável usando o getData()método do dataTransferobjeto.
  • Segundo, anexe o elemento arrastável como um elemento filho do elemento de destino para soltar.
  • Terceiro, remova a hideclasse do draggableelemento.

O código a seguir mostra o dropmanipulador de eventos completo:

function drop(e) {
    e.target.classList.remove('drag-over');

    // get the draggable element
    const id = e.dataTransfer.getData('text/plain');
    const draggable = document.getElementById(id);

    // add it to the drop target
    e.target.appendChild(draggable);

    // display the draggable element
    draggable.classList.remove('hide');
}Linguagem de código:  JavaScript  ( javascript )

Se você arrastar e soltar o elemento arrastável agora, ele deverá funcionar conforme o esperado.

O seguinte mostra o arquivo app.js completo:

/* draggable element */
const item = document.querySelector('.item');

item.addEventListener('dragstart', dragStart);

function dragStart(e) {
    e.dataTransfer.setData('text/plain', e.target.id);
    setTimeout(() => {
        e.target.classList.add('hide');
    }, 0);
}


/* drop targets */
const boxes = document.querySelectorAll('.box');

boxes.forEach(box => {
    box.addEventListener('dragenter', dragEnter)
    box.addEventListener('dragover', dragOver);
    box.addEventListener('dragleave', dragLeave);
    box.addEventListener('drop', drop);
});


function dragEnter(e) {
    e.preventDefault();
    e.target.classList.add('drag-over');
}

function dragOver(e) {
    e.preventDefault();
    e.target.classList.add('drag-over');
}

function dragLeave(e) {
    e.target.classList.remove('drag-over');
}

function drop(e) {
    e.target.classList.remove('drag-over');

    // get the draggable element
    const id = e.dataTransfer.getData('text/plain');
    const draggable = document.getElementById(id);

    // add it to the drop target
    e.target.appendChild(draggable);

    // display the draggable element
    draggable.classList.remove('hide');
}Linguagem de código:  JavaScript  ( javascript )

E aqui está o link para a demonstração .

Resumo

  • Adicione a draggablepropriedade com o valor true a um elemento para torná-lo arrastável.
  • Os eventos dragstart, drage dragendsão acionados no elemento arrastável.
  • Os eventos dragenter, dragover, dragleaveou dropsão acionados no destino de soltar.
  • Chame os event.preventDefault()manipuladores de eventos dragentere dragoverpara tornar um elemento um destino de descarte válido.
  • Use o event.dataTransferobjeto com os métodos setData()e getData()para transferir dados na operação de arrastar e soltar.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *