From 22c57e5b41a1bb5af5ebd21f7ac92f4cc4e3d379 Mon Sep 17 00:00:00 2001 From: MVA Global Fret Date: Tue, 5 May 2026 14:07:48 +0200 Subject: [PATCH] CTA emerges from the plane when it reaches center MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hide the gold pill button at page load (opacity 0, scale 0.05, translated 27 vh up — roughly where the plane is when it crosses the viewport center). When the plane's progress reaches 0.5, the tick loop adds a `.revealed` class to .cta-btn; CSS variables flip and a 1.2 s spring transition lands the button at viewport center at full size. Pulse halo (::after) is dormant until the .revealed class lands, so it doesn't waste cycles on a hidden element. Hover scale (1.04) re-introduced on `.cta-btn.revealed:hover` with the original 0.32 s transition so it doesn't fight the slow emerge tween. Plane and parcel logic untouched. Co-Authored-By: Claude Opus 4.6 --- css/parallax.css | 41 ++++++++++++++++++++++++++++++++++------- js/intro-scene.js | 14 ++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/css/parallax.css b/css/parallax.css index 6726f1f..d7a1d71 100644 --- a/css/parallax.css +++ b/css/parallax.css @@ -117,12 +117,23 @@ html, body { .layer-three { display: block; z-index: 2; } -/* ── BOUTON CTA centré ──────────────────────────────────────────────────── */ +/* ── BOUTON CTA centré ──────────────────────────────────────────────────── + État caché : positionné là où l'avion est au centre de sa course + (~27% au-dessus du centre du viewport), à scale ≈ 0. Quand le JS + ajoute la classe `.revealed` (au moment où l'avion atteint p ≥ 0.5), + les variables CSS basculent et le bouton « sort » de l'avion en + grossissant jusqu'à sa taille finale au centre. */ .cta-btn { + --cta-y: -27vh; /* offset vertical : 0 = centré */ + --cta-scale: 0.05; + --cta-opacity: 0; + position: absolute; top: 50%; left: 50%; - transform: translate(-50%, -50%); + transform: translate(-50%, calc(-50% + var(--cta-y))) scale(var(--cta-scale)); + opacity: var(--cta-opacity); + pointer-events: none; z-index: 10; display: inline-flex; align-items: center; @@ -142,12 +153,25 @@ html, body { 0 20px 60px rgba(197, 165, 90, 0.55), 0 0 0 0 rgba(197, 165, 90, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.45); - transition: box-shadow 0.32s cubic-bezier(0.2, 0.8, 0.2, 1), - transform 0.32s cubic-bezier(0.2, 0.8, 0.2, 1); + transition: + transform 1.2s cubic-bezier(0.34, 1.5, 0.64, 1), + opacity 0.5s ease 0.05s, + box-shadow 0.32s cubic-bezier(0.2, 0.8, 0.2, 1); } -.cta-btn:hover { - transform: translate(-50%, -50%) scale(1.04); +.cta-btn.revealed { + --cta-y: 0vh; + --cta-scale: 1; + --cta-opacity: 1; + pointer-events: auto; +} + +/* Hover seulement après la révélation, avec une transition rapide */ +.cta-btn.revealed:hover { + --cta-scale: 1.04; + transition: + transform 0.32s cubic-bezier(0.2, 0.8, 0.2, 1), + box-shadow 0.32s cubic-bezier(0.2, 0.8, 0.2, 1); box-shadow: 0 28px 75px rgba(197, 165, 90, 0.7), 0 0 0 12px rgba(197, 165, 90, 0.12), @@ -177,9 +201,12 @@ html, body { inset: -3px; border-radius: 50px; border: 2px solid rgba(197, 165, 90, 0.55); - animation: ctaPulse 2.8s ease-out infinite; + animation: none; /* halo dormant tant que le bouton n'est pas révélé */ pointer-events: none; } +.cta-btn.revealed::after { + animation: ctaPulse 2.8s ease-out 1s infinite; /* démarre après l'arrivée du bouton */ +} @keyframes ctaPulse { 0% { transform: scale(1); opacity: 0.7; } 100% { transform: scale(1.18); opacity: 0; } diff --git a/js/intro-scene.js b/js/intro-scene.js index 54f1957..067d9a1 100644 --- a/js/intro-scene.js +++ b/js/intro-scene.js @@ -239,6 +239,13 @@ window.addEventListener('deviceorientation', (e) => { const root = document.documentElement; +/* ── Révélation du CTA ───────────────────────────────────────────────── + Quand l'avion arrive au centre de l'écran (p ≥ 0.5), on bascule la + classe `.revealed` sur le bouton. La CSS gère l'animation (translate + du haut vers le centre + scale 0.05 → 1, ~1.2 s). */ +const ctaBtn = document.querySelector('.cta-btn'); +let ctaRevealed = false; + /* ── Render loop ───────────────────────────────────────────────────────── */ const clock = new THREE.Clock(); @@ -278,6 +285,13 @@ function tick() { } updateParcels(dt, t); + /* Au moment où l'avion atteint le centre, on déclenche la sortie du + CTA (l'animation CSS s'en occupe ensuite). One-shot. */ + if (!ctaRevealed && p >= 0.5) { + ctaRevealed = true; + ctaBtn?.classList.add('revealed'); + } + /* Avec nez à -X et up = +Y : - rotation.z = PITCH (négatif = nez en l'air) - rotation.x = ROLL