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

JavaScript Discussion :

Détecter collision div et les déplacer


Sujet :

JavaScript

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 82
    Points : 43
    Points
    43
    Par défaut Détecter collision div et les déplacer
    Bonjour,

    Je rencontre une impasse. J'espère que quelqu'un saura me donner un coup de pouce.

    Je place des points dynamiquement sur une map. Certains points se superposent. (cf PJ (points 5, 6, 7 ,8))



    Je cherche à détecter les collisions entre ces différentes div et déplacer les div jusqu'à ce qu'il n'y ait plus de collision.

    J'utilise ceci pour le moment:

    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
    32
    33
    34
    35
    36
    37
    38
    39
    function collision_() {
        if (arguments.length > 1) {
            for (var x = 0; x < arguments.length; x++) {
                for (var y = 1; y < arguments.length; y++) {
                    if (x == y) {
                        continue;
                    }
                    if (collision(arguments[x], arguments[y])) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
     
    function collision($div1, $div2) {
          var x1 = $div1.offset().left;
          var y1 = $div1.offset().top;
          var h1 = $div1.outerHeight(true);
          var w1 = $div1.outerWidth(true);
          var b1 = y1 + h1;
          var r1 = x1 + w1;
          var x2 = $div2.offset().left;
          var y2 = $div2.offset().top;
          var h2 = $div2.outerHeight(true);
          var w2 = $div2.outerWidth(true);
          var b2 = y2 + h2;
          var r2 = x2 + w2;
     
     
          if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false;
              //console.log($div1.id + ' w1: '+w1, $div1.id +' w2: '+w2, $div2.id +' h1: '+h1, $div2.id +' h2: '+h2);
          return true;
     
     
    }
     
    collision_($("#pt_TCOLYMPE2-3_1_881"),$("#pt_TCOLYMPE2-3_2_604"),$("#pt_TCSAULIRE1_3_655"),$("#pt_BICHE_4_691"),$("#pt_MARMOTTE_5_687"),$("#pt_GEAI_6_686"),$("#pt_GEAI_7_2365"),$("#pt_BELETTE_8_677"),$("#pt_BLANCHOT__9_678"),$("#pt_BLANCHOT__10_2348"),$("#pt_BLANCHOT__11_2286"),$("#pt_LAPIN_12_672"),$("#pt_LAPIN_13_671"));
    Les collisions semblent parfaitement détecter mais je ne sais pas comment procéder pour les déplacer jusqu'à ce qu'il n'y ait plus de collision.
    Si quelqu'un peut m'éclairer, je suis preneur

    Merci par avance

  2. #2
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Et comment veux-tu les déplacer exactement ? Je veux dire, ce sont des coordonnées d'une carte, si on les bouge ça perd un peu de son sens non ?

  3. #3
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Salut,

    je pense à un système de répulsion comme sur Music Map

    C'est une sorte de simulation physique. Je pense qu'on peut faire ça simplement avec une fonction récursive qui calcule des « forces » sur chaque div. À chaque étape, on traite chaque div et on regarde avec combien d'autres divs elle est en collision. On lui assigne une force dans la direction qui va bien (on fait la somme des directions vers les autres divs et on inverse). À l'étape suivante, on commence par appliquer les forces en déplaçant légèrement les divs. Et on regarde s'il y a encore des collisions, et on recommence tant que c'est nécessaire.

    Ça a l'air compliqué comme ça mais en fait il n'y a rien de plus méchant que des calculs de distance (théorème de Pythagore).

    Je vais prendre quelques moments pour écrire un code qui marche à peu près. Je te laisse chercher en même temps

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 82
    Points : 43
    Points
    43
    Par défaut
    Yes merci, c'est exactement cela.
    J'avais déjà codé ça en AS3 il y a 2 ou 3ans et je dois maintenant faire l'évolution en HTML5 mais je suis beaucoup moins à l'aise.

    C'est plus où moins ce que je faisais en AS3 en ajoutant un trait de liaison (shape, moveto lineto) entre le point déplacé et le point d'origine pour conserver une cohérence de lecture.

    Merci encore, je cherche aussi de mon côté ;-)

  5. #5
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Alors, tu as trouvé quelque chose ?

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 82
    Points : 43
    Points
    43
    Par défaut
    Non, j'ai essayé un bon paquet de lignes de code sans arriver au résultat souhaité. Je désespère

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 82
    Points : 43
    Points
    43
    Par défaut
    Et toi?

  8. #8
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Moi j'ai un truc, mais ça manque un peu de fluidité, tu me diras ce que tu en penses

    Code html : 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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    <!DOCTYPE html>
    <html lang=fr>
    <head>
       <meta charset=utf-8>
       <title>Collision de divs</title>
       <style>
       
       div {
          width: 16px;
          height: 16px;
          background: #eee;
          border: solid 2px #999;
          border-radius: 16px;
          position: absolute;
          /* une transition juste pour faire classe */
          -webkit-transition: left 100ms ease-out, top 100ms ease-out;
          -moz-transition: left 100ms ease-out, top 100ms ease-out;
          -ms-transition: left 100ms ease-out, top 100ms ease-out;
          -o-transition: left 100ms ease-out, top 100ms ease-out;
          transition: left 100ms ease-out, top 100ms ease-out;
       }
       body {
          position: relative;
          margin: 0;
       }
       
       </style>
       <script>
       "use strict";
     
       // constantes représentant les dimensions des divs
       // mettre les mêmes valeurs que dans le CSS (ne pas oublier les
       // marges, padding et bordures)
       const DIV_WIDTH  = 20;
       const DIV_HEIGHT = 20;
       
       // l'espace minimum qu'on veut avoir entre les divs
       const SPACE = 2;
       
       // facteur pour atténuer ou augmenter l'effet des forces
       // 1 = normal, 0.5 = petit, 2 = grand
       const FACTEUR = 1;
       
       function repousse( divs ){
          // 1. on applique les forces précédemment calculées
          // une force = un déplacement en x + un déplacement en y
          divs.forEach(div => {
             // la 1re fois, force n'est pas définie, on prend donc (0,0)
             // comme force par défaut
             var force = div.force || { x: 0, y: 0 };
             
             // j'ai choisi de stocker les coordonnées directement sur la
             // div pour ne pas avoir à refaire parseInt sur style.left et
             // style.top à chaque fois
             var style = div.style;
             var x = div.x || parseInt(style.left, 10);
             var y = div.y || parseInt(style.top, 10);
             
             x += force.x;
             y += force.y;
             
             style.left = x + "px";
             style.top = y + "px";
             
             div.x = x;
             div.y = y;
             
             // on prépare la liste des collisions sur chaque div
             div.collisions = [];
          });
          
          // 2. on détermine les nouvelles collisions
          // c'est un parcours triangulaire en O(n*n/2), il y a sans doute
          // moyen de faire mieux
          var encore = false;
          divs.forEach((divA, i) => {
             // on fait slice(i + 1) car les divs avant ont déjà été vues
             divs.slice(i + 1).forEach(divB => {
                var distX = divA.x - divB.x;
                var absX = Math.abs(distX);
                if (absX > DIV_WIDTH + SPACE) return;
                var distY = divA.y - divB.y;
                var absY = Math.abs(distY);
                if (absY > DIV_HEIGHT + SPACE) return;
                encore = true;
                
                // calcul des puissances de répulsion : plus les divs sont
                // proches, plus la force est puissante
                var signeX = distX > 0 ? 1 : -1;
                var puissX = FACTEUR * signeX * (DIV_WIDTH + SPACE - absX);
                var signeY = distY > 0 ? 1 : -1;
                var puissY = FACTEUR * signeY * (DIV_HEIGHT + SPACE - absY);
                divA.collisions.push({ x: puissX, y: puissY });
                divB.collisions.push({ x: -puissX, y: -puissY });
             });
          });
          
          // 3a. si pas de collisions à ce point, on a fini
          if (!encore) return;
          
          // 3b. si collisions, on calcule les nouvelles forces
          divs.forEach(div => {
             var force = div.collisions.reduce(( result, collision ) => ({
                x: result.x + collision.x,
                y: result.y + collision.y
             }), { x: 0, y: 0 });
             div.force = { x: force.x, y: force.y };
          });
          
          // 4. on refait un appel récursif
          setTimeout(() => repousse(divs), 250);
       }
       
       document.addEventListener("DOMContentLoaded", e => {
          // calcule le centre de la page
          var O = {
             x: window.innerWidth / 2,
             y: window.innerHeight / 2
          };
          
          // on récupère la liste des divs sous forme de tableau
          var divs = Array.map(document.querySelectorAll("div"), $ => $);
          
          // au départ, on décale légèrement chaque div
          divs.forEach(div => {
             var dx = 25 - Math.round(50 * Math.random());
             var dy = 25 - Math.round(50 * Math.random());
             div.style.left = O.x + dx + "px";
             div.style.top = O.y + dy + "px";
          });
          
          // appelle la fonction récursive
          repousse(divs);
       });
       
       </script>
    </head>
    <body>
     
    <div></div> <div></div> <div></div> <div></div>
    <div></div> <div></div> <div></div> <div></div>
    <div></div> <div></div> <div></div> <div></div>
    <div></div> <div></div> <div></div> <div></div>
     
    </body>
    </html>

Discussions similaires

  1. [VB.NET] [newbie] Charger plusieurs .X et les déplacer
    Par tamagotchi dans le forum DirectX
    Réponses: 12
    Dernier message: 12/04/2006, 11h45
  2. [Javascript] Détecter collision de deux objets <img>
    Par Invité4 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 04/04/2006, 08h54
  3. [CSV] Détecter le séparateur pour les fichiers CSV
    Par JavaEli dans le forum Langage
    Réponses: 1
    Dernier message: 30/11/2005, 23h42
  4. bouger une div selon les coordonnées de la souris
    Par 10-nice dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 21/09/2005, 15h31
  5. [DIV] contenir les elements dans la balise div
    Par kemodo dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 11/10/2004, 20h43

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