Blog / JavaScript & Interactions

Animation « Ajouter au panier » en JavaScript : burst + vol vers le panier

Créez une micro-interaction d'ajout au panier qui donne envie de cliquer : bouton magnétique, burst de particules, vol en courbe de Bézier jusqu'au panier et compteur animé. Vanilla JS, zéro dépendance, accessible.

Sur une boutique, le clic « ajouter au panier » est le moment qui compte. Une micro-interaction bien faite — l'article qui s'envole vers le panier, un petit burst, le compteur qui s'incrémente — confirme l'action, la rend satisfaisante et lève le doute (« est-ce que ça a marché ? »). C'est un levier de conversion simple. Cet article décrit l'effet Magnetic Add to Cart, l'effet gratuit du sprint Black Friday de novembre 2026 sur Effect.Labs, en JavaScript vanilla, sans aucune dépendance, accessible et 60fps.

Définition — Micro-interaction. Une petite animation de feedback déclenchée par une action utilisateur (clic, survol). Son rôle : confirmer, guider, et donner du plaisir. Ici, quatre briques se combinent : bouton magnétique, particules, vol vers le panier, compteur.

1. Le bouton magnétique

Le bouton « attire » légèrement le curseur : sur pointermove, on calcule l'écart entre le curseur et le centre du bouton, et on applique une translation proportionnelle. Sur pointerleave, on réinitialise.

btn.addEventListener('pointermove', function (e) {
  var r = btn.getBoundingClientRect();
  var mx = e.clientX - (r.left + r.width / 2);
  var my = e.clientY - (r.top + r.height / 2);
  btn.style.transform = 'translate(' + (mx * 0.22) + 'px,' + (my * 0.35) + 'px)';
});
btn.addEventListener('pointerleave', function () { btn.style.transform = ''; });

2. Le burst de particules

Au clic, on génère une dizaine de petites particules (de simples <span>) à la position du bouton, projetées dans des directions aléatoires via des variables CSS et une keyframe. Léger, et auto-nettoyé après l'animation.

for (var i = 0; i < 14; i++) {
  var p = document.createElement('span');
  p.className = 'atc-particle';
  p.style.left = x0 + 'px'; p.style.top = y0 + 'px';
  var a = Math.random() * 6.2832, d = 24 + Math.random() * 46;
  p.style.setProperty('--dx', Math.cos(a) * d + 'px');
  p.style.setProperty('--dy', Math.sin(a) * d + 'px');
  scene.appendChild(p);
  setTimeout(function () { p.remove(); }, 650); // cleanup
}
.atc-particle { animation: atc-burst .6s ease-out forwards; }
@keyframes atc-burst {
  to { transform: translate(-50%,-50%) translate(var(--dx), var(--dy)) scale(.2); opacity: 0; }
}

3. Le vol vers le panier (courbe de Bézier)

Le cœur de l'effet : un clone de l'article suit une courbe de Bézier quadratique du bouton jusqu'à l'icône panier. Le point de contrôle placé au-dessus des deux extrémités donne cette belle trajectoire en arc.

// P(t) = (1-t)²·P0 + 2(1-t)t·C + t²·P1
var cx = (x0 + x1) / 2, cy = Math.min(y0, y1) - 70; // point de contrôle au-dessus
(function anim(t) {
  var k = Math.min((t - t0) / 620, 1);
  var e = k < .5 ? 2*k*k : 1 - Math.pow(-2*k+2, 2)/2;  // easing
  var m = 1 - e;
  var x = m*m*x0 + 2*m*e*cx + e*e*x1;
  var y = m*m*y0 + 2*m*e*cy + e*e*y1;
  chip.style.transform = 'translate(-50%,-50%) translate(' + (x-x0) + 'px,' + (y-y0) + 'px) scale(' + (1 - .55*e) + ')';
  if (k < 1) requestAnimationFrame(anim);
  else { chip.remove(); bump(); }   // à l'arrivée : incrémente le panier
})(t0);

4. Le compteur qui réagit

À l'arrivée du clone, on incrémente le badge et on rejoue une petite animation de « pop » (et un tressaut du panier). L'astuce pour rejouer une animation CSS : retirer la classe, forcer un reflow (void el.offsetWidth), la remettre.

function bump() {
  n++; countEl.textContent = n;
  countEl.classList.remove('atc-pop'); void countEl.offsetWidth; countEl.classList.add('atc-pop');
}

Le code complet (bouton magnétique, burst, vol et compteur réunis) est disponible directement sur la page Boutons du cataloguecet effet est gratuit.

Performance et accessibilité

Tout repose sur des transform/opacity (composés par le GPU) et un seul requestAnimationFrame par clic : c'est fluide même sur mobile. Les garde-fous :

  • Un vrai <button> : utilisable au clavier et annoncé par les lecteurs d'écran.
  • prefers-reduced-motion : on saute le magnétisme, les particules et le vol — on garde uniquement l'incrément du compteur (le feedback essentiel).
  • Cleanup : particules et clone sont retirés du DOM après l'animation (pas de fuite).

Ce que ChatGPT et v0 ne font pas

Demandez une animation « add to cart » à un générateur : vous obtenez souvent une transition droite (translate linéaire) sans âme. Ce qui est régulièrement oublié :

  • La courbe de Bézier : l'arc (point de contrôle au-dessus) est ce qui rend le vol naturel ; l'IA propose une ligne droite.
  • prefers-reduced-motion : presque jamais géré → animation imposée à ceux qui l'ont désactivée.
  • Le cleanup DOM : les particules/clones restent souvent dans le DOM (fuite mémoire sur usage répété).
  • Le bouton magnétique sur pointermove avec reset propre, rarement inclus.

Questions fréquentes

Peut-on l'utiliser avec React, Vue ou Svelte ?

Oui : JavaScript vanilla, aucune dépendance npm. Dans React, encapsuler la logique dans un useEffect avec cleanup (retirer les particules/clones au démontage) ; dans Svelte, onMount/onDestroy.

Comment l'adapter à « ajouter aux favoris » ?

Même mécanique : remplacez l'icône panier par un cœur, l'article volant par un ❤️, et incrémentez un compteur de favoris. Le code est agnostique du contexte.

Le code complet, prêt à l'emploi

Cet effet est gratuit ce mois-ci. Copiez-collez le code et adaptez-le à votre panier. Accès à 800+ autres effets premium avec l'abonnement.

Rejoindre les fondateurs — 9,90 € / mois