Hover✨ Premium

Gravity Drag

Trois balles colorées flottent dans un cadre et se laissent attraper à la souris ou au doigt : relâchez et la gravité les ramène au sol avec rebond et friction. Lancez-les d'un geste sec pour observer leur trajectoire, ou posez-les délicatement pour les empiler.

JSPhysicsDrag

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Hover comprend 48 effets, dont 5 gratuits. Découvrir la catégorie →

3 exemples d'usage

Fond animé — landing page d'un studio de jeux indépendants — Gravity Drag exemple 1

① Fond animé — landing page d'un studio de jeux indépendants

QuandLe visiteur arrive sur la page d'accueil du studio ; trois balles colorées portant les mots JOUE, CRÉE, GAGNE tombent en arrière-plan pendant qu'il lit l'accroche. Il peut les attraper à la souris si la curiosité l'emporte.
PourquoiUn fond vivant, interactif mais non intrusif, pose l'univers du studio sans détourner l'attention du message principal — le texte reste prioritaire grâce au dégradé opaque en haut.
RéglagesPosition de la zone : absolute inset:0, hauteur 360 px. Balles en dégradés violet, or et cyan pour rappeler la palette du studio. Label gd380-label masqué (display:none) ; fond de la racine transparent.
Tri de priorités — backlog d'un outil de gestion de projet — Gravity Drag exemple 2

② Tri de priorités — backlog d'un outil de gestion de projet

QuandDans l'outil SaaS, chaque tâche urgente est représentée par une balle (URGENT, NORMAL, PLUS TARD). L'utilisateur les glisse et les lâche pour les empiler ; la physique traduit l'énergie mise dans la priorisation.
PourquoiLa métaphore physique rend le tri intuitif : lancer une balle vers le haut signale l'urgence, l'empiler au fond indique qu'elle peut attendre. L'interaction directe est plus satisfaisante qu'un drag-and-drop de liste.
RéglagesBarre d'en-tête 48 px ; zone sous la barre. Balles rouge, orange, bleu à 50 px. Repères de colonnes fantômes (Haute/Moyenne/Basse) en pointer-events:none pour orienter sans bloquer l'interaction.
Mini-jeu de café — appli mobile d'une chaîne de cafés — Gravity Drag exemple 3

③ Mini-jeu de café — appli mobile d'une chaîne de cafés

QuandDans l'appli, un mini-jeu interstitiel invite l'utilisateur à lancer des grains de café dans une tasse avant de passer commande. Il saisit une balle, la balance et la relâche d'un geste vif.
PourquoiUn instant de jeu avant la commande crée de l'attachement à la marque et augmente le temps passé dans l'appli. La physique du lancé rend le geste satisfaisant même avec une mauvaise visée.
RéglagesPalette café (bruns chauds, fond #100702). Zone de jeu au-dessus d'une cible en pointillés matérialisée par l'emoji tasse. Balles stylisées en grains de café (dégradé brun radial).

Comment ça marche

Chaque balle est un div.gd380-ball positionné en absolu dans la zone .gd380-zone (300 px de haut). Ses propriétés d'état (x, y, vx, vy, isDragging) sont gardées dans un tableau JavaScript. La boucle requestAnimationFrame met à jour chaque balle à chaque image avec un pas normalisé à 60 images/s : f = dt / 16.67.

Quand une balle n'est pas saisie : la gravité ajoute 0,5 × f à vy ; si y + 50 dépasse la hauteur de la zone, la balle rebondit (vy × −0,65) et perd un peu de vitesse horizontale (vx × 0,85). Si elle sort par un côté, vx est inversé. Quand elle est saisie (mousedown ou touchstart), sa position suit le curseur ou le doigt dans le repère de la zone, avec l'offset du point de prise mémorisé ; au relâcher (mouseup/touchend), la vélocité est déduite de la différence de position sur les 20 dernières ms pour permettre les lancers.

Accessibilité

  • Toucher : les événements touchstart, touchmove et touchend permettent de saisir et lancer les balles au doigt sur mobile et tablette. preventDefault() bloque le défilement de la page pendant la saisie.
  • Clavier : l'effet ne propose pas de navigation au clavier. Les balles ne sont pas des boutons et ne reçoivent pas le focus. Si un usage accessible est requis, ajoutez des <button> invisibles qui appliquent une impulsion prédéfinie à chaque balle via Entrée.
  • Mouvement réduit : sous prefers-reduced-motion: reduce, la boucle ne démarre pas ; les balles restent à leur position initiale, visibles et lisibles, sans tomber ni rebondir.
  • Rôle décoratif : les balles portent les mots DRAG, ME, UP en anglais — un appel à l'action intégré au visuel. Si votre contexte exige un texte accessible différent, ajoutez un aria-label sur .gd380-zone.

Compatibilité navigateur

DOM pur et CSS, aucune dépendance. IntersectionObserver disponible depuis Chrome 51, Firefox 55, Safari 12.1. Physique par requestAnimationFrame normalisée sur le temps écoulé : même comportement sur écran 60 Hz et 120 Hz. Non vérifié sur Safari réel ; attendu complet.

Chrome 51+✓ Complet (mesuré)
Firefox 55+✓ Complet (mesuré)
Safari 12.1+✓ Attendu complet (non mesuré)
Edge 79+✓ Complet (mesuré)
Mobile iOS 12.2+✓ Complet au toucher (non mesuré)
Android Chrome 51+✓ Complet au toucher (non mesuré)

Sans JavaScript, les trois balles s'affichent à leur position initiale, fixes. Sans IntersectionObserver, la boucle tourne aussi hors écran.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec votre achat) :

index.html — structure
<div class="fx-0380-root">
  <div class="gd380-zone">
    <div class="gd380-ball ball-1" data-ball="0" style="left:50px;top:60px">DRAG</div>
    <div class="gd380-ball ball-2" data-ball="1" style="left:150px;top:90px">ME</div>
    <div class="gd380-ball ball-3" data-ball="2" style="left:250px;top:50px">UP</div>
  </div>
  <span class="gd380-label" aria-hidden="true">Attrapez et lancez les balles</span>
</div>

Paiement unique, sans abonnement — le code est à toi pour toujours

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
Gravité (JS — vy += 0.5 * f) 0,5 px/image² (normalisé 60 fps) 0,2 donne une chute lunaire ; 1,5 une chute rapide. Sur un écran 120 Hz, la normalisation maintient le même ressenti qu'à 60 Hz.
Rebond (JS — vy *= -0.65) 65 % de la vitesse conservée 0,8 donne des rebonds très élastiques ; 0,3 un arrêt rapide. 1,0 est physiquement impossible et crée un cycle infini.
Friction au sol (JS — vx *= 0.85) 85 % de la vitesse horizontale conservée 0,98 donne un long glissement ; 0,5 arrête la balle presque instantanément.
Taille des balles (CSS — .gd380-ball { width, height }) 50 px Ajustez aussi les collisions avec le sol (y + 50 > zoneH) au même pixel que la hauteur réelle de la balle.
Couleurs (CSS — .gd380-ball.ball-1, .ball-2, .ball-3) gradient indigo, violet, rose Remplacez les background par vos couleurs brand. La propriété box-shadow suit si vous la conservez sur fond sombre.

FAQ

Oui. Ajoutez des div.gd380-ball.ball-4 dans .gd380-zone avec un style left/top initial, et ajoutez la couleur dans le CSS. Le script parcourt automatiquement tous les .gd380-ball avec querySelectorAll. Au-delà de 6 balles, les collisions entre elles ne sont pas gérées : elles se traversent.
Oui. L'effet simule la gravité, le rebond sur les murs et le sol, mais pas les collisions entre balles. Elles se traversent mutuellement. Pour ajouter des collisions circulaires, calculez la distance entre chaque paire de balles à chaque image et inversez leurs vélocités si la distance est inférieure à la somme de leurs rayons.
Faites glisser la balle rapidement dans la direction souhaitée avant de relâcher. Le script mesure la différence de position sur les 20 dernières millisecondes pour en déduire la vélocité de lancer. Plus le geste est vif, plus la balle part vite.