Que fait Scroll Zoom Reveal ?
Effet de défilement prêt à l'emploi, sans dépendance :
- Scène épinglée plein écran : un titre surplombe une scène assombrie qui remplit la fenêtre.
- Dolly + recul : la scène se stabilise légèrement, puis la « caméra » recule. La scène se révèle être sur un écran d'ordinateur portable (la bordure et la base apparaissent).
- Réapparition de l'application : les panneaux d'éditeur (barre d'outils, hiérarchie, propriétés, timeline) glissent en place et la scène se réduit dans son panneau.
- Fondu du texte ci-dessous (
data-zr-fade), puis une galerie à onglets avec fondu enchaîné et un curseur coulissant.
Tous les fichiers prêts à l'emploi se trouvent dans assets/ à côté de ce fichier :
| Fichier | Objectif |
|---|---|
assets/zoom-reveal.css | Tous les styles (jetons de thème sur .zr) |
assets/zoom-reveal.js | Composant + fadeds + galerie. Exporte window.ZoomReveal, auto-initialise [data-zoom-reveal] / [data-zr-gallery] / [data-zr-fade] |
assets/oled-field.js | Optionnel. Champ de sous-pixels OLED réactif au curseur (window.OledField, auto-initialise [data-zr-oled]). Les styles sont dans zoom-reveal.css |
assets/placeholder-scenes.js | Optionnel. Peint de manière procédurale les œuvres de substitution originales sur canvas (ZRScenes.drawCity, ZRScenes.drawCanyon) jusqu'à ce que des images réelles existent |
assets/demo.html | Page de démonstration complète et fonctionnelle. Partez de ce balisage. |
Comment l'utiliser sur un site
- Copiez les assets dans le projet (par exemple
public/zoom-reveal/ousrc/vendor/zoom-reveal/). Copiezplaceholder-scenes.jsuniquement s'il n'y a pas encore d'œuvre réelle. - Lisez
assets/demo.htmlet copiez le bloc<section class="zr" data-zoom-reveal>…</section>(ainsi que le bloc de galerie si souhaité). Conservez exactement la structure des classes :
section.zr[data-zoom-reveal] ← la longueur de défilement est ici (--zr-length)
.zr-sticky ← arrière-plan fixe de 100vh
.zr-glow (lueur ambiante optionnelle)
.zr-device ← mis à l'échelle par JS
.zr-lid > .zr-display
.zr-viewport > .zr-media > img | video | canvas ← VOTRE SCÈNE
.zr-chrome > .zr-panel.zr-toolbar / .zr-left / .zr-right / .zr-bottom (interface utilisateur de l'application optionnelle)
.zr-base (base de l'ordinateur portable ; supprimer pour un moniteur/tablette)
.zr-scrim + header.zr-intro ← titre au-dessus de la scène, disparaît en premier
.zr-caption ← petite légende, apparaît à la fin
- Chargez
zoom-reveal.cssdans<head>etzoom-reveal.jsà la fin de<body>. - Remplacez le média : remplacez le canvas de démonstration par la scène réelle :
- Image :
<img src="scene.avif" alt="" decoding="async">. Exportez-la au moins avec la taille de la fenêtre × DPR (2560–3200px de large). L'effet commence avec l'image remplissant tout l'écran. - Vidéo avec défilement :
<video data-zr-scrub muted playsinline preload="auto" src="scene.mp4"></video>. Le JS mappe la progression du défilement surcurrentTime. Encodez chaque image comme une image clé pour que la recherche reste fluide :ffmpeg -i in.mov -c:v libx264 -g 1 -crf 22 -an -movflags +faststart scene.mp4.
- Image :
- Réécrivez tout le texte (sourcil, titre, légende, étiquettes des panneaux, nom de fichier, étiquettes de la galerie) pour correspondre au site. Ne livrez jamais le texte fictif « Orbit / Forge » de la démo.
- Thème avec les jetons sur
.zr:--zr-bg,--zr-fg,--zr-muted,--zr-accent,--zr-length(distance de défilement, défaut360vh).
Options
Passez du JSON dans l'attribut, par exemple data-zoom-reveal='{"maxWidth":1000,"viewport":{"top":0,"right":0,"bottom":0,"left":0}}', ou construisez-le en JS : new ZoomReveal(el, options).
| Option | Défaut | Signification |
|---|---|---|
maxWidth | 1180 | Largeur maximale finale de l'affichage (px) |
widthRatio / heightRatio | 0.82 / 0.64 | Taille finale de l'affichage par rapport à la fenêtre |
aspect | 0.625 | Hauteur ÷ largeur de l'affichage (16:10). Téléphone ≈ 2.16, ultra-large ≈ 0.42 |
overscan | 1.04 | Distance au-delà de la fenêtre où commence l'affichage (masque la bordure) |
dolly | 1.14 | Zoom interne initial du média ; se stabilise à 1 |
lift | 0.035 | De combien l'appareil s'élève à la fin |
timeline | voir JS | Fenêtres de progression [début,fin] pour intro, dolly, zoom, chrome, caption |
viewport | {top:6.5,right:21,bottom:22,left:15} | Marges finales (% de l'affichage) du panneau de scène à l'intérieur de l'interface utilisateur. Mettez tout à 0 et supprimez .zr-chrome pour un pur recul « scène → écran de l'appareil » sans interface d'application |
onProgress | — | Fonction de rappel fn(p) avec progression 0..1 |
Événements : la section émet zr:resize avec {width, height, finalWidth}, la taille en pixels à laquelle le média est disposé. Utilisez-la pour dimensionner les canvas ou choisir une source d'image.
React / Next.js
Importez le CSS globalement. Supprimez data-zoom-reveal du balisage et construisez-le manuellement pour qu'il soit lié au cycle de vie du composant ('use client' dans Next) :
useEffect(() => {
import('./zoom-reveal/zoom-reveal.js').then(() => { // enregistre window.ZoomReveal
const zr = new window.ZoomReveal(ref.current, { maxWidth: 1100 });
const gal = galRef.current && new window.ZoomReveal.Gallery(galRef.current);
window.ZoomReveal.initFades();
cleanup = () => zr.destroy();
});
let cleanup = () => {};
return () => cleanup();
}, []);
Convertissez class → className et style="--v:78%" → style={{'--v':'78%'}}.
Champ de pixels OLED (effet de survol du curseur)
Un arrière-plan plein écran de fines barres de sous-pixels RVB, faiblement éclairées. Le déplacement du curseur agite une petite simulation de fluide. Les pixels le long du chemin s'allument, grandissent et changent de couleur du violet au cyan au vert lime au blanc chaud, puis la lueur dérive dans la direction du curseur, se propage et s'estompe. Un clic ou un tapotement produit une ondulation. Lorsque le curseur est inactif (et sur les écrans tactiles), un lent « curseur fantôme » le maintient en vie. Le rendu est un fragment shader WebGL1, la simulation est une petite grille CPU, et elle ne s'exécute que lorsque la section est visible à l'écran. Sans WebGL, elle revient à un projecteur CSS.
Utilisez-le derrière un bloc de spécifications/statistiques, un héros ou une bande d'appel à l'action. N'importe quel élément fonctionne : ajoutez class="zr-oled" data-zr-oled, placez le contenu à l'intérieur, chargez zoom-reveal.css + oled-field.js. Le composant insère lui-même le canvas. Voir le bloc « OLED PIXEL FIELD » dans assets/demo.html.
<section class="zr-oled" data-zr-oled='{"cell":7}'>
<div class="your-content">…stats / headline…</div>
</section>
<script src="oled-field.js"></script>
| Option | Défaut | Signification |
|---|---|---|
cell | 6 | Pixels CSS par pixel (3 barres de sous-pixels). 5–9 semble correct ; utilisez une valeur plus grande sur mobile pour la performance |
radius | 2.4 | Rayon du pinceau en cellules |
strength | 0.55 | Quantité de lumière ajoutée par le curseur. Les valeurs par défaut sont délibérément subtiles ; 1 est audacieux |
decay | 0.94 | Atténuation par image ; plus élevé = traînées plus longues (0.92 court … 0.97 long) |
flow | 0.55 | Distance de dérive de la lueur dans la direction du curseur |
diffusion | 0.35 | Vitesse de propagation de la lueur |
base | 0.09 | Luminosité de la grille non éclairée |
palette | ['#5a3cff','#1fd6ff','#b6ff4a','#fff4d8'] | 4 couleurs, basse → haute énergie. Adaptez à la marque, par exemple chaud ['#ff3c5a','#ff9a1f','#ffe14a','#fff8e8'] |
ambient / ripples | true | Curseur fantôme quand inactif / ondulation au clic |
Pour un aspect plus audacieux (proche d'un effet de vitrine), utilisez {"radius":3.2,"strength":1,"decay":0.962,"flow":0.9}. Gardez les valeurs par défaut subtiles derrière les sections riches en texte.
API : const f = new OledField(el, opts), f.pulse(clientX, clientY) (déclenche une ondulation depuis le code), f.destroy() (appelez dans le nettoyage React). Donnez au texte au-dessus du champ une légère text-shadow sombre pour qu'il reste lisible par-dessus les traînées lumineuses.
Pièges (vérifiez-les avant de terminer)
- Le sticky se casse si un ancêtre de
.zraoverflow: hidden/auto/clipoutransform. Utilisezoverflow-x: clipsurbodysi le débordement horizontal doit être masqué. - N'enveloppez pas
.zrdans des bibliothèques de défilement fluide qui transforment la page (Locomotive v4 etc.). Lenis convient. - L'appareil est disposé grand et mis à l'échelle vers le bas, donc les médias restent nets. Ne mettez pas de tailles fixes en px à l'intérieur de
.zr-device: utilisezem(1em = 1% de la largeur de l'affichage). - La réduction de mouvement est gérée : la section se désépingle et affiche l'état final ; la galerie arrête la lecture automatique ; le champ OLED continue de réagir au curseur mais abandonne le curseur fantôme et les ondulations.
- Les animations se mettent en pause dans les onglets d'arrière-plan (requestAnimationFrame s'arrête). Lorsque vous testez le champ OLED dans un panneau de navigateur, gardez la page visible ou elle semblera figée.
- En dessous d'environ 500px de large, l'ordinateur portable est petit. Envisagez
{"widthRatio":0.92}ou unaspectcorrespondant à un cadre de téléphone sur mobile. - Testez en défilant lentement du haut vers le bas dans le navigateur aux largeurs de bureau et mobile. Assurez-vous que le titre disparaisse avant le début du recul, qu'aucune bordure ne soit visible au début et que la légende ne chevauche pas la base.
- Utilisez des œuvres originales ou sous licence et du texte. Cette compétence recrée la technique de mouvement ; ne copiez pas les images, rendus de produits ou textes d'une autre marque.
