1/** 2 * blocs.js â Animations JS spécifiques aux blocs PUNCH Gutenberg 3 * 4 * Anime : 5 * - .bloc-mots-rotateur__rotateur : glitch + rotation de mots 6 * - .bloc-mots-rotateur__inner : déploiement trapèze (scaleY) 7 * - .bloc-teaser-video__arrow : déploiement triangle (scaleY) 8 * 9 * Dépend de GSAP + ScrollTrigger (fournis par le parent revalice). 10 */ 11(function () { 12 'use strict'; 13 14 function init() { 15 if (typeof gsap === 'undefined') return; 16 if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; 17 18 // ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 19 // 1. Rotateur de catégories â effet GLITCH brutaliste 20 // ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 21 const rotEl = document.querySelector('.bloc-mots-rotateur__rotateur'); 22 if (rotEl) { 23 let cats = []; 24 try { cats = JSON.parse(rotEl.dataset.mots || '[]'); } catch (e) {} 25 if (cats.length > 1) { 26 let i = 0; 27 let timer = null; 28 const rand = (min, max) => Math.random() * (max - min) + min; 29 30 function glitchBurst(onDone) { 31 const tl = gsap.timeline({ onComplete: onDone }); 32 for (let k = 0; k < 5; k++) { 33 tl.to(rotEl, { 34 x : rand(-12, 12), 35 y : rand(-4, 4), 36 skewX : rand(-8, 8), 37 opacity : rand(0.3, 1), 38 textShadow : `${rand(-5,5).toFixed(1)}px 0 #fff, ${rand(-5,5).toFixed(1)}px 0 #000`, 39 duration : 0.05, 40 ease : 'none' 41 }); 42 } 43 tl.to(rotEl, { 44 x: 0, y: 0, skewX: 0, opacity: 1, textShadow: 'none', 45 duration: 0.08, ease: 'power2.out' 46 }); 47 } 48 49 function tick() { 50 glitchBurst(() => { 51 i = (i + 1) % cats.length; 52 rotEl.textContent = cats[i]; 53 glitchBurst(); 54 }); 55 } 56 57 const io = new IntersectionObserver(entries => { 58 entries.forEach(entry => { 59 if (entry.isIntersecting && !timer) { 60 timer = setInterval(tick, 2800); 61 } else if (!entry.isIntersecting && timer) { 62 clearInterval(timer); 63 timer = null; 64 } 65 }); 66 }, { threshold: 0.3 }); 67 io.observe(rotEl); 68 } 69 } 70 71 // ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 72 // 2. Trapèze catégories qui se déplie 73 // ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 74 const trapEl = document.querySelector('.bloc-mots-rotateur__inner'); 75 if (trapEl && typeof ScrollTrigger !== 'undefined') { 76 gsap.set(trapEl, { scaleY: 0, transformOrigin: 'top center' }); 77 gsap.to(trapEl, { 78 scaleY: 1, 79 duration: 1.4, 80 ease: 'back.out(1.4)', 81 scrollTrigger: { 82 trigger: trapEl, 83 start: 'top 80%', 84 toggleActions: 'play none none reverse' 85 } 86 }); 87 } 88 89 // ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 90 // 3. Triangle teaser qui se déplie 91 // ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 92 const triEl = document.querySelector('.bloc-teaser-video__arrow'); 93 if (triEl && typeof ScrollTrigger !== 'undefined') { 94 gsap.set(triEl, { scaleY: 0, transformOrigin: 'top center' }); 95 gsap.to(triEl, { 96 scaleY: 1, 97 duration: 1.4, 98 ease: 'back.out(1.4)', 99 scrollTrigger: { 100 trigger: triEl, 101 start: 'top 80%', 102 toggleActions: 'play none none reverse' 103 } 104 }); 105 } 106 } 107 108 if (document.readyState === 'loading') { 109 document.addEventListener('DOMContentLoaded', init); 110 } else { 111 init(); 112 } 113})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.