{"id":1376,"date":"2026-08-31T07:00:00","date_gmt":"2026-08-31T05:00:00","guid":{"rendered":"https:\/\/iconoclaste.net\/blog\/?p=1376"},"modified":"2026-08-13T12:59:08","modified_gmt":"2026-08-13T10:59:08","slug":"sonia-saute","status":"publish","type":"post","link":"https:\/\/iconoclaste.net\/blog\/2026\/08\/31\/sonia-saute\/","title":{"rendered":"Sonia saute"},"content":{"rendered":"\n<!--\n  SAUTCORDE \u2013 jouet interactif iconoclaste.net\n  \u2192 Coller TOUT ce code dans un bloc \u00ab HTML personnalis\u00e9 \u00bb (Gutenberg)\n  \u2192 Fonctionne aussi dans un widget HTML ou un template\n  iconoclaste.net \u2013 2026-08-13\n\n  Comportement :\n  - Image 01 centr\u00e9e \u00e0 100 % de la largeur de l\u2019article, responsive, sans bordure\n  - Pr\u00e9chargement visible avec barre rose (#ff33ff) du site\n  - Clic OU survol (mouseenter) sur l\u2019image 01 \u2192 lance la s\u00e9quence 02 \u2192 13\n  - \u00c0 la fin de 13 : retour automatique sur 01 + attente du prochain clic\/survol\n  - Chaque d\u00e9clenchement : le personnage compte \u00ab un \u00bb, \u00ab deux \u00bb, \u00ab trois \u00bb\u2026 (SpeechSynthesis)\n  - Compteur sous l\u2019animation : \u00ab Sonia a saut\u00e9 \u00e0 la corde X fois. \u00bb\n-->\n\n<div id=\"iconoclaste-sautcorde\">\n  <div id=\"sautcorde-stage\">\n    <img id=\"sautcorde-img\"\n         src=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/08\/saut_corde_01.webp\"\n         alt=\"Saut \u00e0 la corde\"\n         loading=\"eager\"\n         decoding=\"async\">\n\n    <!-- Pr\u00e9chargement -->\n    <div id=\"sautcorde-preload\">\n      <div class=\"sautcorde-progress-wrap\">\n        <span>chargement<\/span>\n        <div class=\"sautcorde-progress-bar\">\n          <div class=\"sautcorde-progress-fill\" id=\"sautcorde-progress-fill\"><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <div id=\"sautcorde-counter\">Sonia a saut\u00e9 \u00e0 la corde 0 fois.<\/div>\n<\/div>\n\n<style>\n  #iconoclaste-sautcorde {\n    position: relative;\n    width: 100%;\n    max-width: 100%;\n    margin: 0 auto 1.5em;\n    line-height: 0;\n    background: transparent;\n    cursor: default;\n    -webkit-tap-highlight-color: transparent;\n    user-select: none;\n    -webkit-user-select: none;\n    text-align: center;\n  }\n\n  #sautcorde-stage {\n    position: relative;\n    width: 100%;\n    line-height: 0;\n  }\n\n  #iconoclaste-sautcorde img {\n    display: block;\n    width: 100%;\n    height: auto;\n    margin: 0 auto;\n    border: none !important;\n    outline: none !important;\n    box-shadow: none !important;\n    vertical-align: top;\n    pointer-events: none;\n    background: transparent;\n  }\n\n  \/* Barre de pr\u00e9chargement \u2013 couleur du site *\/\n  #sautcorde-preload {\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 12px;\n    display: flex;\n    justify-content: center;\n    pointer-events: none;\n    z-index: 5;\n  }\n\n  .sautcorde-progress-wrap {\n    background: rgba(0, 0, 0, 0.72);\n    color: #fff;\n    padding: 6px 14px 8px;\n    border-radius: 4px;\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 12px;\n    text-align: center;\n    white-space: nowrap;\n  }\n\n  .sautcorde-progress-bar {\n    width: 140px;\n    height: 4px;\n    background: #333;\n    margin: 5px auto 0;\n    border-radius: 2px;\n    overflow: hidden;\n  }\n\n  .sautcorde-progress-fill {\n    height: 100%;\n    width: 0%;\n    background: #ff33ff; \/* rose iconoclaste *\/\n    transition: width 0.12s linear;\n  }\n\n  #iconoclaste-sautcorde.ready {\n    cursor: pointer;\n  }\n\n  #iconoclaste-sautcorde.playing {\n    cursor: default;\n  }\n\n  #iconoclaste-sautcorde.ready #sautcorde-preload {\n    display: none;\n  }\n\n  #sautcorde-counter {\n    display: inline-block;\n    line-height: 1.35;\n    margin-top: 14px;\n    padding: 7px 16px;\n    text-align: center;\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 14px;\n    color: #fff;\n    background: #ff33ff;\n    border-radius: 3px;\n    cursor: default;\n    pointer-events: none;\n  }\n<\/style>\n\n<script>\n(function () {\n  \"use strict\";\n\n  if (window.__iconoclasteSautCordeInit) return;\n  window.__iconoclasteSautCordeInit = true;\n\n  const BASE = \"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/08\/saut_corde_\";\n  const TOTAL = 13;\n  const SPEED = 75; \/\/ ms par image\n\n  \/\/ Nombres en fran\u00e7ais pour le comptage oral\n  const NUMBERS = [\n    \"un\", \"deux\", \"trois\", \"quatre\", \"cinq\",\n    \"six\", \"sept\", \"huit\", \"neuf\", \"dix\",\n    \"onze\", \"douze\", \"treize\", \"quatorze\", \"quinze\",\n    \"seize\", \"dix-sept\", \"dix-huit\", \"dix-neuf\", \"vingt\",\n    \"vingt et un\", \"vingt-deux\", \"vingt-trois\", \"vingt-quatre\", \"vingt-cinq\",\n    \"vingt-six\", \"vingt-sept\", \"vingt-huit\", \"vingt-neuf\", \"trente\"\n  ];\n\n  const frames = [];\n  for (let i = 1; i <= TOTAL; i++) {\n    frames.push(BASE + String(i).padStart(2, \"0\") + \".webp\");\n  }\n\n  function init() {\n    const container   = document.getElementById(\"iconoclaste-sautcorde\");\n    const img         = document.getElementById(\"sautcorde-img\");\n    const counterEl   = document.getElementById(\"sautcorde-counter\");\n    const progressFill = document.getElementById(\"sautcorde-progress-fill\");\n    const preloadEl   = document.getElementById(\"sautcorde-preload\");\n\n    if (!container || !img || !counterEl || !progressFill) return;\n\n    let state = \"loading\"; \/\/ loading | idle | playing\n    let timer = null;\n    let jumpCount = 0;\n    let loaded = 0;\n\n    function updateProgress() {\n      const pct = Math.round((loaded \/ TOTAL) * 100);\n      progressFill.style.width = pct + \"%\";\n    }\n\n    function onAllLoaded() {\n      state = \"idle\";\n      container.classList.add(\"ready\");\n      \/\/ Le preload se cache via CSS (.ready #sautcorde-preload)\n    }\n\n    \/\/ Pr\u00e9chargement avec suivi de progression\n    frames.forEach(function (src) {\n      const preload = new Image();\n      preload.onload = preload.onerror = function () {\n        loaded++;\n        updateProgress();\n        if (loaded >= TOTAL) {\n          onAllLoaded();\n        }\n      };\n      preload.src = src;\n    });\n\n    function updateCounter() {\n      counterEl.textContent = \"Sonia a saut\u00e9 \u00e0 la corde \" + jumpCount + \" fois.\";\n    }\n\n    function sayNumber(n) {\n      if (!(\"speechSynthesis\" in window)) return;\n      try {\n        window.speechSynthesis.cancel();\n        const text = (n >= 1 && n <= NUMBERS.length)\n          ? NUMBERS[n - 1]\n          : String(n);\n        const u = new SpeechSynthesisUtterance(text);\n        u.lang = \"fr-FR\";\n        u.rate = 1.55;\n        u.pitch = 1.25;\n        u.volume = 1;\n        window.speechSynthesis.speak(u);\n      } catch (e) {}\n    }\n\n    function showFrame(index) {\n      img.src = frames[index];\n    }\n\n    function startJump() {\n      if (state !== \"idle\") return;\n\n      state = \"playing\";\n      container.classList.add(\"playing\");\n      jumpCount++;\n      updateCounter();\n      sayNumber(jumpCount);\n\n      let frame = 1; \/\/ 02\n\n      function next() {\n        if (frame >= TOTAL) {\n          showFrame(0);\n          state = \"idle\";\n          container.classList.remove(\"playing\");\n          timer = null;\n          return;\n        }\n        showFrame(frame);\n        frame++;\n        timer = setTimeout(next, SPEED);\n      }\n\n      showFrame(1);\n      frame = 2;\n      timer = setTimeout(next, SPEED);\n    }\n\n    \/\/ D\u00e9clencheurs uniquement quand ready (idle)\n    container.addEventListener(\"click\", function (e) {\n      e.preventDefault();\n      startJump();\n    });\n\n    container.addEventListener(\"mouseenter\", function () {\n      startJump();\n    });\n\n    container.addEventListener(\"touchstart\", function (e) {\n      if (state === \"idle\") {\n        e.preventDefault();\n        startJump();\n      }\n    }, { passive: false });\n\n    document.addEventListener(\"visibilitychange\", function () {\n      if (document.hidden && timer) {\n        clearTimeout(timer);\n        timer = null;\n        showFrame(0);\n        state = \"idle\";\n        container.classList.remove(\"playing\");\n      }\n    });\n  }\n\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\"DOMContentLoaded\", init);\n  } else {\n    init();\n  }\n})();\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>chargement Sonia a saut\u00e9 \u00e0 la corde 0 fois.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[269,31],"tags":[308,101,253,236],"class_list":["post-1376","post","type-post","status-publish","format-standard","hentry","category-experiences","category-fuzzout","tag-bande-dessinee","tag-girl","tag-girl-dance","tag-manara"],"_links":{"self":[{"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/posts\/1376","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/comments?post=1376"}],"version-history":[{"count":1,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/posts\/1376\/revisions"}],"predecessor-version":[{"id":1377,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/posts\/1376\/revisions\/1377"}],"wp:attachment":[{"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/media?parent=1376"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/categories?post=1376"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/tags?post=1376"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}