IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

React Discussion :

drag and drop: faire un rendu fluide pour des blocs de différentes hauteur


Sujet :

React

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 275
    Points : 113
    Points
    113
    Par défaut drag and drop: faire un rendu fluide pour des blocs de différentes hauteur
    Bonjour, et bonne année à toutes et tous...

    Comme indiqué dans le titre, je m'essaye au drag and drop avec React ( sans librairie: pour apprendre ! )

    Je déplace donc des blocs ( éléments <li>) dans une liste de repas (contenant des ingrédients)
    De base, mes éléments ont tous la même hauteur (même nombre d'ingrédients), donc le drag and drop est fluide entre ces éléments.

    Mais si je rajoute un repas, celui-ci ne contenant pas d'ingrédients, sa hauteur est plus petite ! Du coup,
    le déplacement est moins fluide lorsque que l'on passe sur un autre élément.

    Je partage mon code simplifié ici
    J'ai enlevé du code et des fonctionnalités pour me concentrer sur le problème du moment.

    Donc ajoutez un repas et faites glisser ce repas où vous voulez: "tremblements" logiques pendant le glissé sur un autre élément à cause de la taille différente

    Je n'ai pas vraiment de pistes: j'avais essayé d'enregistrer la hauteur du (petit) repas puis de lui donner la taille de l'élément sur lequel il glissait
    et enfin de lui redonner sa taille lors du dragEnd. Mais je ne sui pas satisfait du résultat.
    Peut-être n'est-ce pas la bonne solution, ou alors je ne l'ai pas fait correctement.

    Si vous avez des pistes, je vous remercie par avance.
    Et si vous voyez également un moyen de faire le drag and drop plus simple ou plus dans les règles de l'art...
    Je remarque aussi que si je sors de la zone (<ul>) pendant le glissement, le rendu n'est pas propre:
    l'ombre retourne au point de départ, alors que l'élément s'affichera à la place où on l'a déposé...

    Laurent.

    P.S: désolé pour le css, ce n'est pas mon souci du moment et j'avoue ne pas vraiment être un artiste à ce niveau.

  2. #2
    Membre éclairé
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 386
    Points : 788
    Points
    788
    Par défaut
    Bonjour,

    Il faut sauvegarder les coordonnées des cibles au drag start
    puis utiliser ces dernières pour détecter le swap lors d'un hover.

    Cela permet d'éviter d'avoir des zones cibles dont les positions
    changent en permanence, et donc l'effet de scintillement disparaît.

    Bonne journée.

  3. #3
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Bonjour,
    Donc ajoutez un repas et faites glisser ce repas où vous voulez: "tremblements" logiques pendant le glissé sur un autre élément à cause de la taille différente
    ...
    Si vous avez des pistes, je vous remercie par avance.
    un moyen simple est d'ajouter une hauteur minimale à tes éléments name
    Code css : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    .name {
      width: 150px;
      border: 1px solid black;
      background-color: rgb(58, 52, 52);
      margin: 10px;
      padding: 3px;
      color: white;
      min-height: 12em;   /* par exemple */
    }

  4. #4
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 275
    Points : 113
    Points
    113
    Par défaut
    Ce serait pratique de définir une hauteur minimale !
    Mais le bouton ajouter un aliment ( qui est fonctionnel sur mon ordi ) permet d'ajouter autant d'aliments que l'on souhaite.
    J'ai donc essayé d'améliorer nom code

    Nouvelle variable:
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    const [mealsList, setMealsList] = useState(null)

    Initialisée dans le dragStart:
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    setMealsList(document.querySelectorAll(".name"))

    Utilisée dans le dragOver:
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    mealsList[draggedIndex].style.height = `${mealsList[index].offsetHeight}px`

    Puis dans le dragEnd:
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    Array.from(mealsList).map(element => element.removeAttribute('style'))

    Dans le sens "glisser vers le haut" un repas vide d'aliments, le rendu est fluide.
    Mais lorsqu'il faut redescendre, la taille de l'élément augmente d'abord ( d'où un effet de pousser vers le bas de la cible ) et ensuite on va pouvoir glisser.

    Ce serait mieux dans l'ordre inverse, mais je ne vois pas comment m'y prendre.

  5. #5
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Une autre approche peut-être.

    Décaler via un translate de l'élément survolé de la hauteur de l'élément en déplacement.

    Je te livre la fonction handleDragOver qui semble fonctionner, pas testé en plein, il faudrait sûrement voir les conditions pour le décalage.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
      const handleDragOver = (e, index) => {
        e.preventDefault();
     
        const mealList = document.querySelectorAll(".name");
     
        if (index !== draggedIndex) {
          mealsList[draggedIndex].style.translate = "0";      
     
          mealList[draggedIndex].classList.remove("dragging");
          mealList[index].classList.add("dragging");
     
          const updatedMealList = [...meals];
          const temp = updatedMealList[index];
          // décalage de l'élément survolé
          let sens = 1;
          const top1 = mealsList[index].offsetTop;
          const top2 = mealsList[draggedIndex].offsetTop;
          if(top1 > top2) sens *= -1;
          const decalage = mealsList[draggedIndex].offsetHeight * sens;
     
          mealsList[index].style.translate = `0 ${decalage}px`;
     
          updatedMealList[index] = updatedMealList[draggedIndex];
          updatedMealList[draggedIndex] = temp;
     
          //mealsList[draggedIndex].style.height = `${mealsList[index].offsetHeight}px`
     
          setMeals(updatedMealList);
          setDraggedIndex(index);
        }
      };

  6. #6
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    En relisant la réponse je me rend compte que tu gères l'essentiel sur le onDragOver, événement répété en boucle tant que l'on est sur un élément cible, il serait plus judicieux de faire cette gestion sur le onDragEnter.

  7. #7
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2020
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2020
    Messages : 275
    Points : 113
    Points
    113
    Par défaut
    En effet, j'ai entre-temps rectifié le dragEnter à la place de dragOver...

    Je n'aurais pas pensé au translate, mais ça fonctionne bien !

    Sauf que ... il apparaît un autre problème qui n'existait pas avant !

    Le comportement de l'ombre de l'élément en déplacement.

    Si je prend le repas 3 pour le déplacer à la place du repas 2, la translation se fait comme il faut et lorsque je relâche, l'ombre se dirige vers l'endroit d'où elle est partie.
    C'est à dire vers le repas 2 ( qui a été déplacé grâce à la translation ).
    Mais le repas 3 apparaît ensuite à sa place.

    Je ne comprends d'ailleurs pas vraiment comment fonctionne l'ombre dans un drag and drop. Ça me permettrait peut-être de régler ce problème.

    Pour être sûr (même si j'ai vérifié): nous sommes bien d'accord que lorsqu'on parle de onDragEnter ou onDragOver, ces évènements se déclenchent quand le curseur passe sur le bloc cible.

  8. #8
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 112
    Points
    44 112
    Par défaut
    Sauf que ... il apparaît un autre problème qui n'existait pas avant !
    Le comportement de l'ombre de l'élément en déplacement.
    Pas bien repéré le soucis


    Pour être sûr (même si j'ai vérifié): nous sommes bien d'accord que lorsqu'on parle de onDragEnter ou onDragOver, ces évènements se déclenchent quand le curseur passe sur le bloc cible.
    Tout à fait. L'événement est déclenché quand le pointer entre dans la zone cible et non pas lorsque l'élément glissé entre dans la zone.

Discussions similaires

  1. Réponses: 6
    Dernier message: 18/12/2007, 09h16
  2. Faire bouger un clip (simple drag and drop)
    Par yoyot dans le forum ActionScript 3
    Réponses: 3
    Dernier message: 15/12/2007, 20h13
  3. Meilleur méthode pour du drag and drop ASP.NET
    Par sspizer dans le forum ASP.NET
    Réponses: 1
    Dernier message: 20/07/2007, 14h10
  4. Drag and drop pour control en VBA
    Par cbleas dans le forum VBA Access
    Réponses: 2
    Dernier message: 10/03/2007, 10h30
  5. Faire un drag and drop depuis IE vers un TListView
    Par ALEX77 dans le forum Composants VCL
    Réponses: 8
    Dernier message: 11/11/2004, 15h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo