Se rendre au contenu

Welcome .


Sign u

Cette question a été signalée
27 Vues

Ce snippet prend un texte HTML encodé (ex. <strong>…</strong>), le décode puis affiche une explosion de confettis autour du texte. Plug-and-play, sans librairie externe, relançable au clic.

Utilisez l’attribut data-encoded (ou un <pre> enfant) pour fournir le contenu encodé.


<!-- ============== Apple-Style Confetti Text (Auto, 5s, Decode HTML) ==============
USAGE :
- Placez votre HTML ENCODÉ dans data-encoded (ou à défaut dans un <pre> enfant).
- L’animation démarre seule au chargement, dure ~5 s, puis s’arrête (une seule fois).
=============================================================================== -->
<div class="sw-apple-hero" data-encoded="&lt;strong&gt;Bravo&nbsp;!&lt;/strong&gt;"></div>

<style>
  .sw-apple-hero{
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 32vh;             /* zone aérée, fond blanc */
    padding: clamp(16px, 4vw, 40px);
    background: #fff;
    border-radius: 20px;
    overflow: visible;
    isolation: isolate;           /* confettis au-dessus sans affecter le reste */
  }
  .sw-apple-hero .sw-text{
    font-family: -apple-system, system-ui, "SF Pro Display", Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
    font-weight: 700;
    font-size: clamp(28px, 7vw, 72px);   /* grand, responsive */
    line-height: 1.05;
    letter-spacing: .2px;
    color: #111;                  /* contraste sobre */
    text-align: center;
    white-space: pre-wrap;
  }

  /* Confetti */
  .sw-piece{
    position: absolute;
    width: var(--w,6px);
    height: var(--h,10px);
    background: var(--c,#777);
    left: var(--x,0px);
    top: var(--y,0px);
    transform: translate(0,0) rotate(0deg);
    opacity: 1;
    border-radius: var(--r,3px);
    pointer-events: none;
    will-change: transform, opacity, filter;
    animation:
      sw-fall var(--dur,1400ms) cubic-bezier(.2,.7,.2,1) forwards,
      sw-twirl var(--dur,1400ms) linear forwards;
  }
  @keyframes sw-fall{
    to{
      transform: translate(var(--dx,0px), var(--dy,120px)) rotate(var(--rot,180deg));
      opacity: 0;
    }
  }
  @keyframes sw-twirl{
    to{ filter: hue-rotate(120deg) saturate(1.05); }
  }

  /* Respecte l’accessibilité : pas d’animation si l’utilisateur la réduit */
  @media (prefers-reduced-motion: reduce){
    .sw-piece{ animation: none !important; opacity: 0 !important; }
  }
</style>

<script>
(function(){
  // Décode &lt;strong&gt;Bravo&lt;/strong&gt; -> <strong>Bravo</strong>
  function decodeHTML(encoded){
    const ta = document.createElement('textarea');
    ta.innerHTML = encoded;
    return ta.value;
  }

  // Rendu du texte décodé dans .sw-apple-hero
  function renderDecoded(el){
    let encoded = el.getAttribute('data-encoded') || '';
    if(!encoded){
      const pre = el.querySelector('pre');
      encoded = pre ? pre.innerHTML.trim() : (el.textContent || '').trim();
    }
    el.innerHTML = `<span class="sw-text">${decodeHTML(encoded)}</span>`;
  }

  // Émet un petit lot de confettis autour du centre du texte
  function emitConfetti(host, qty){
    const text = host.querySelector('.sw-text');
    if(!text) return;

    const hRect = host.getBoundingClientRect();
    const tRect = text.getBoundingClientRect();
    const cx = (tRect.left - hRect.left) + tRect.width/2;
    const cy = (tRect.top  - hRect.top)  + tRect.height*0.45;

    const palette = [
      '#111111', '#2E2E2E', '#5E5E5E',  // neutres élégants
      '#007AFF', '#34C759', '#FF9500',   // accents iOS
      '#FF2D55', '#AF52DE'               // touches vives
    ];

    for(let i=0;i<qty;i++){
      const p = document.createElement('i');
      p.className = 'sw-piece';

      // tailles / formes
      const w = 4 + Math.random()*7;     // 4–11px
      const h = 7 + Math.random()*11;    // 7–18px
      const rounded = Math.random() < 0.35 ? (Math.min(w,h)/2)+'px' : '3px';

      // angle + portée douce
      const angle = Math.random() * Math.PI * 2;
      const power = 40 + Math.random()*110; // 40–150px
      const dx = Math.cos(angle) * power;
      const dy = Math.sin(angle) * power + (30 + Math.random()*70);

      // rotation / durée
      const rot = (Math.random()*540 - 270).toFixed(1) + 'deg';
      const dur = (1000 + Math.random()*900) | 0; // 1.0–1.9s

      p.style.setProperty('--x', cx + 'px');
      p.style.setProperty('--y', cy + 'px');
      p.style.setProperty('--w', w + 'px');
      p.style.setProperty('--h', h + 'px');
      p.style.setProperty('--r', rounded);
      p.style.setProperty('--dx', dx + 'px');
      p.style.setProperty('--dy', dy + 'px');
      p.style.setProperty('--rot', rot);
      p.style.setProperty('--dur', dur + 'ms');
      p.style.setProperty('--c', palette[(Math.random()*palette.length)|0]);

      host.appendChild(p);
      p.addEventListener('animationend', ()=> p.remove(), {once:true});
    }
  }

  // Lecture automatique : ~5 s puis stop (une seule fois)
  function autoplayOnce(host){
    if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;

    if (host.dataset.played === '1') return;
    host.dataset.played = '1';

    const start = performance.now();
    const duration = 5000; // 5 s
    const tickEvery = 120; // ms entre lots
    let lastTick = start - tickEvery;

    function frame(now){
      if (now - lastTick >= tickEvery){
        lastTick = now;
        // quantité proportionnelle à la largeur du texte (mais bornée)
        const text = host.querySelector('.sw-text');
        const w = text ? text.getBoundingClientRect().width : 320;
        const qty = Math.min(18, Math.max(8, Math.round(w / 80)));
        emitConfetti(host, qty);
      }
      if (now - start < duration){
        requestAnimationFrame(frame);
      }
    }
    requestAnimationFrame(frame);
  }

  function init(){
    document.querySelectorAll('.sw-apple-hero').forEach(host=>{
      renderDecoded(host);
      autoplayOnce(host);
    });
  }

  if(document.readyState === 'loading'){
    document.addEventListener('DOMContentLoaded', init);
  }else{
    init();
  }
})();
</script>
</script>
Ignorer
Publications associées Réponses Vues Activité
0
août 25
43
0
août 25
5
0
août 25
3
0
août 25
100
0
août 25
39