Cet article explique les bases du glisser-déposer.
Créer du contenu déplaçable
Dans la plupart des navigateurs, les sélections de texte, les images et les liens sont déplaçables par défaut. Par exemple, si vous faites glisser un lien sur une page Web, vous verrez une petite case avec un et l'URL que vous pouvez insérer dans la barre d'adresse ou sur le bureau ou accédez au lien. Pour rendre d'autres types de contenus déplaçables, vous utiliser les API de glisser-déposer HTML5.
Pour rendre un objet déplaçable, définissez draggable=true
sur cet élément. À peu près
tout élément pouvant être glissé, y compris les images, les fichiers, les liens, les fichiers,
sur votre page.
L'exemple suivant crée une interface pour réorganiser les colonnes qui ont été
avec la grille CSS. Le balisage de base des colonnes ressemble à ceci, avec
l'attribut draggable
pour chaque colonne définie sur true
:
<div class="container">
<div draggable="true" class="box">A</div>
<div draggable="true" class="box">B</div>
<div draggable="true" class="box">C</div>
</div>
Voici le code CSS des éléments "container" et "box". Le seul CSS associé
la fonctionnalité de déplacement est cursor: move
. Le reste du code contrôle la mise en page et le style du conteneur.
et les éléments
de zone.
.container {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 10px;
}
.box {
border: 3px solid #666;
background-color: #ddd;
border-radius: .5em;
padding: 10px;
cursor: move;
}
À ce stade, vous pouvez faire glisser les éléments, mais rien d'autre ne se passe. Pour ajouter vous devez utiliser l'API JavaScript.
Écouter les événements de déplacement
Pour surveiller le processus de déplacement, vous pouvez écouter l'un des événements suivants:
Pour gérer le flux de déplacement, vous avez besoin d'un type d'élément source (où le déplacement la charge utile des données (ce que vous faites glisser) et une cible (une zone à attraper la baisse). L'élément source peut correspondre à presque n'importe quel type d'élément. La La cible est la zone de dépôt ou l'ensemble de zones de dépôt qui accepte les données de l'utilisateur que vous essayez de faire tomber. Tous les éléments ne peuvent pas être des cibles. Par exemple, votre cible ne peut pas en tant qu'image.
Commencer et terminer une séquence de déplacement
Après avoir défini les attributs draggable="true"
pour votre contenu, associez une
Gestionnaire d'événements dragstart
pour lancer la séquence de déplacement pour chaque colonne.
Ce code définit l'opacité de la colonne sur 40% lorsque l'utilisateur commence à la faire glisser. puis remettez-le à 100% à la fin de l'événement de déplacement.
function handleDragStart(e) {
this.style.opacity = '0.4';
}
function handleDragEnd(e) {
this.style.opacity = '1';
}
let items = document.querySelectorAll('.container .box');
items.forEach(function (item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragend', handleDragEnd);
});
Vous pouvez voir le résultat dans la démonstration de Glitch suivante. Faites glisser un élément.
l'opacité change. Étant donné que l'élément source contient l'événement dragstart
, la définition
this.style.opacity
à 40% donne à l'utilisateur un retour visuel sur cet élément
la sélection actuelle est déplacée. Lorsque vous déposez l'élément, l'élément source
revient à 100% d'opacité, même si vous n'avez pas encore défini le comportement de dépôt.
Ajouter des repères visuels supplémentaires
Pour aider l'utilisateur à comprendre comment interagir avec votre interface, utilisez la
Gestionnaires d'événements dragenter
, dragover
et dragleave
Dans cet exemple,
les colonnes sont des cibles de dépôt
en plus d’être déplaçables. Aidez l’utilisateur à
le comprendre en faisant en sorte que la bordure soit en pointillés lorsqu'ils tiennent un élément déplacé sur un
. Par exemple, dans votre CSS, vous pouvez créer une classe over
pour
qui sont des cibles de dépôt:
.box.over {
border: 3px dotted #666;
}
Ensuite, dans votre code JavaScript, configurez les gestionnaires d'événements, ajoutez la classe over
lorsque
la colonne est glissée et la supprime lorsque l'élément glissé quitte l'élément. Dans
le gestionnaire dragend
, nous veillons également à supprimer les classes à la fin de
faites glisser.
document.addEventListener('DOMContentLoaded', (event) => {
function handleDragStart(e) {
this.style.opacity = '0.4';
}
function handleDragEnd(e) {
this.style.opacity = '1';
items.forEach(function (item) {
item.classList.remove('over');
});
}
function handleDragOver(e) {
e.preventDefault();
return false;
}
function handleDragEnter(e) {
this.classList.add('over');
}
function handleDragLeave(e) {
this.classList.remove('over');
}
let items = document.querySelectorAll('.container .box');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
});
Voici quelques points à aborder dans ce code:
L'action par défaut pour l'événement
dragover
consiste à définir la propriétédataTransfer.dropEffect
sur"none"
La propriétédropEffect
est abordée plus loin sur cette page. Pour l'instant, sachez simplement qu'il empêche le déclenchement de l'événementdrop
. Pour remplacer , appeleze.preventDefault()
. Une autre bonne pratique consiste à renvoyerfalse
dans ce même gestionnaire.Le gestionnaire d'événements
dragenter
permet d'activer/de désactiver la classeover
au lieu dedragover
Si vous utilisezdragover
, l'événement se déclenche plusieurs fois lorsque l'utilisateur maintient l'élément déplacé sur une colonne, ce qui entraîne l'activation/désactivation de la classe CSS à plusieurs reprises. Cela fait que le navigateur effectue beaucoup de tâches inutiles d’affichage, ce qui peut affecter l'expérience utilisateur. Nous vous recommandons vivement de réduire redessin, et si vous devez utiliserdragover
, envisagez en limitant ou en bloquant l'écouteur d'événements.
Terminez le lancement
Pour traiter la suppression, ajoutez un écouteur d'événements pour l'événement drop
. Dans le drop
vous devez empêcher le comportement par défaut du navigateur en cas de suppression,
est généralement une redirection agaçante. Pour ce faire, appelez e.stopPropagation()
.
function handleDrop(e) {
e.stopPropagation(); // stops the browser from redirecting.
return false;
}
Veillez à enregistrer le nouveau gestionnaire en même temps que les autres gestionnaires:
let items = document.querySelectorAll('.container .box');
items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragover', handleDragOver);
item.addEventListener('dragenter', handleDragEnter);
item.addEventListener('dragleave', handleDragLeave);
item.addEventListener('dragend', handleDragEnd);
item.addEventListener('drop', handleDrop);
});
Si vous exécutez le code à ce stade, l'élément ne passe pas au nouvel emplacement. À
utilisez la méthode DataTransfer
.
La propriété dataTransfer
contient les données envoyées lors d'un déplacement. dataTransfer
est défini dans l'événement dragstart
, et lu ou géré dans l'événement de dépôt. Appel en cours
e.dataTransfer.setData(mimeType, dataPayload)
vous permet de définir la méthode MIME de l'objet
et la charge utile des données.
Dans cet exemple, nous allons permettre aux utilisateurs de réorganiser l'ordre des colonnes. Pour ce faire, vous devez d'abord stocker le code HTML de l'élément source lorsque le déplacement début:
function handleDragStart(e) {
this.style.opacity = '0.4';
dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
}
Dans l'événement drop
, vous traitez la suppression de colonne en définissant le paramètre
HTML au code HTML de la colonne cible dans laquelle vous avez déposé les données. Ce
inclut la vérification que l'utilisateur ne revient pas dans la même colonne qu'il
que nous avons glissé.
function handleDrop(e) {
e.stopPropagation();
if (dragSrcEl !== this) {
dragSrcEl.innerHTML = this.innerHTML;
this.innerHTML = e.dataTransfer.getData('text/html');
}
return false;
}
Vous pouvez observer le résultat dans la démonstration suivante. Pour que cela fonctionne, vous devez disposer d'un navigateur pour ordinateur. L'API de glisser-déposer n'est pas prise en charge sur mobile. Faire glisser et relâchez la colonne A au-dessus de la colonne B et notez la façon dont elles changent:
Autres propriétés de déplacement
L'objet dataTransfer
expose les propriétés pour fournir un retour visuel à la
l'utilisateur pendant le processus de glissement et contrôler la manière dont chaque cible de dépôt répond à une
un type de données particulier.
dataTransfer.effectAllowed
limite le "type de déplacement" que l'utilisateur peut effectuer sur l'élément. Il est utilisé dans le modèle de traitement par glisser-déposer pour initialiserdropEffect
pendant les événementsdragenter
etdragover
. La propriété peut être définie sur valeurs suivantes:none
,copy
,copyLink
,copyMove
,link
,linkMove
,move
,all
etuninitialized
.dataTransfer.dropEffect
contrôle les commentaires reçus par l'utilisateur pendant les actionsdragenter
etdragover
événements. Lorsque l'utilisateur maintient le pointeur sur un élément cible, Le curseur indique le type d'opération qui va avoir lieu, comme une copie ou un mouvement. L'effet peut prendre l'une des valeurs suivantes:none
,copy
,link
etmove
.e.dataTransfer.setDragImage(imgElement, x, y)
signifie qu'au lieu d'utiliser l'image fantôme par défaut du navigateur, commentaires, vous vous pouvez définir une icône de déplacement.
Importer des fichiers
Cet exemple simple utilise une colonne à la fois comme source de déplacement et cible de déplacement. Ce peut se produire dans une interface utilisateur qui demande à l'utilisateur de réorganiser les éléments. Dans certaines situations, la cible et la source peuvent être des types d'éléments différents, comme dans une interface où l’utilisateur doit sélectionner une image comme image principale d’un produit en en faisant glisser l'image sélectionnée vers une cible.
Le glisser-déposer est fréquemment utilisé pour permettre aux utilisateurs de faire glisser des éléments de leur bureau vers
une application. La principale différence réside dans votre gestionnaire drop
. Au lieu d'utiliser
dataTransfer.getData()
pour accéder aux fichiers, leurs données sont contenues dans le
Propriété dataTransfer.files
:
function handleDrop(e) {
e.stopPropagation(); // Stops some browsers from redirecting.
e.preventDefault();
var files = e.dataTransfer.files;
for (var i = 0, f; (f = files[i]); i++) {
// Read the File objects in this FileList.
}
}
Pour en savoir plus à ce sujet, consultez Glisser-déposer personnalisé :