Cet effet est très utilisé dans le web design moderne : quand l’utilisateur déplace sa souris, une succession d’images apparaît et disparaît avec une animation fluide.
Ajouter la structure HTML dans Elementor
- Dans Elementor, ajoute un Widget HTML sur ta page.
- Colle ce code :
<div class="items"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script>
const imagePaths = [
"https://images.pexels.com/photos/18131871/pexels-photo-18131871.jpeg?w=300&auto=compress&cs=tinysrgb",
"https://images.pexels.com/photos/18398708/pexels-photo-18398708.jpeg?w=300&auto=compress&cs=tinysrgb",
"https://images.pexels.com/photos/18131896/pexels-photo-18131896.jpeg?w=300&auto=compress&cs=tinysrgb",
"https://images.pexels.com/photos/18398385/pexels-photo-18398385.jpeg?w=300&auto=compress&cs=tinysrgb",
"https://images.pexels.com/photos/18398430/pexels-photo-18398430.jpeg?w=300&auto=compress&cs=tinysrgb"
// ajoute ou enlève des images ici
];
document.addEventListener("DOMContentLoaded", function () {
const container = document.querySelector(".items");
let imageIndex = 0;
let lastX = null;
let lastY = null;
const minDistance = 100; // Distance minimale avant apparition d’une nouvelle image
function getDistance(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
return Math.sqrt(dx * dx + dy * dy);
}
function addNewItem(x, y, dx, dy) {
const newItem = document.createElement("div");
newItem.className = "item";
newItem.style.position = "absolute";
newItem.style.left = `${x - 150}px`;
newItem.style.top = `${y - 150}px`;
newItem.style.width = "300px";
newItem.style.height = "300px"; // définit la taille de l'image
newItem.style.pointerEvents = "none";
const img = document.createElement("img");
img.src = imagePaths[imageIndex];
img.style.width = "100%";
img.style.height = "100%";
img.style.objectFit = "contain";
newItem.appendChild(img);
container.appendChild(newItem);
imageIndex = (imageIndex + 1) % imagePaths.length;
const randomRotation = gsap.utils.random(0, 0);
// Normalisation direction
const length = Math.sqrt(dx * dx + dy * dy) || 1;
const dirX = (dx / length) * 80; // Direction et amplitude de l’entrée
const dirY = (dy / length) * 80; // Direction et amplitude de l’entrée
// Animation GSAP
gsap.timeline()
.fromTo(newItem,
{ scale: 1, opacity: 1, rotation: randomRotation, x: -dirX, y: -dirY },
{ scale: 1, opacity: 1, x: 0, y: 0, duration: 0.4, ease: "power2.out" }
)
.to(newItem,
{
scale: 0.3, opacity: 0, duration: 1, ease: "power2.out", delay: 0.05,
onComplete: () => newItem.remove()
}
);
}
container.addEventListener("mousemove", function (event) {
if (lastX === null || lastY === null) {
lastX = event.pageX;
lastY = event.pageY;
return;
}
const dx = event.pageX - lastX;
const dy = event.pageY - lastY;
const distance = getDistance(lastX, lastY, event.pageX, event.pageY);
if (distance > minDistance) {
addNewItem(event.pageX, event.pageY, dx, dy);
lastX = event.pageX;
lastY = event.pageY;
}
});
});
</script>
Ajouter le CSS dans Elementor
Toujours dans le widget HTML va dans Avancé et ensuite CSS Personnalisé, ajoute :
.items {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
will-change: transform, opacity;
z-index: 999; /* passe au-dessus du contenu */
}
.item {
position: absolute;
width: 450px;
height: 600px;
overflow: hidden;
}
.item img {
width: 150%;
height: 250%;
object-fit: cover;
}
Personnaliser l’animation
Tu peux adapter l’effet en modifiant ces lignes clés du script :
Distance minimale avant apparition d’une nouvelle image const minDistance = 100;
→ Plus bas = plus d’images, plus haut = moins d’images.
Direction et amplitude de l’entrée const dirX = (dx / length) * 80; const dirY = (dy / length) * 80;
→ Change 80
pour augmenter/diminuer l’effet de « trajectoire ».
Durée de l’apparition duration: 0.4
→ Plus bas = plus rapide, plus haut = plus lent.
Animation de disparition
Actuellement : scale: 0.3, opacity: 0, duration: 1, ease: "power2.out"
Variante suggérée pour un effet de chute vers le bas :
y: window.innerHeight + 300, opacity: 0, scale: 0.3, duration: 1.2, ease: "power2.in", onComplete: () => item.remove()
Conseils pratiques
- Compression d’images : optimise les images avec TinyPNG ou Squoosh.
- Taille des images : évite les originaux trop lourds (200–400px max pour cet effet).
- Performance mobile : désactive cet effet sur mobile si la fluidité n’est pas optimale.