{"id":2060,"date":"2026-09-24T08:28:09","date_gmt":"2026-09-24T06:28:09","guid":{"rendered":"https:\/\/iconoclaste.net\/blog\/?p=2060"},"modified":"2026-09-24T08:33:47","modified_gmt":"2026-09-24T06:33:47","slug":"clavier-a-2-balles","status":"publish","type":"post","link":"https:\/\/iconoclaste.net\/blog\/2026\/09\/24\/clavier-a-2-balles\/","title":{"rendered":"Clavier \u00e0 2 balles&#8230;"},"content":{"rendered":"\n<!-- \n  PIANO INTERACTIF - GAMME DE DO\n  Compatible mobile avec timeout de s\u00e9curit\u00e9\n-->\n\n<style>\n  #piano-container {\n    width: 100%;\n    position: relative;\n    border: 4px solid #ff0000;\n    box-sizing: border-box;\n    overflow: hidden;\n  }\n\n  #piano-wrapper {\n    position: relative;\n    width: 100%;\n    display: block;\n  }\n\n  #piano-image {\n    width: 100%;\n    height: auto;\n    display: block;\n    vertical-align: bottom;\n  }\n\n  .piano-key {\n    position: absolute;\n    background-color: transparent;\n    cursor: pointer;\n    -webkit-tap-highlight-color: transparent; \/* Supprime le flash bleu sur mobile *\/\n  }\n\n  \/* Position des touches avec DO d\u00e9cal\u00e9 et espace 3px *\/\n  .key-do { left: 3%; width: 10%; height: 90%; top: 5%; }\n  .key-re { left: calc(14% + 3px); width: 10%; height: 90%; top: 5%; }\n  .key-mi { left: calc(26% + 3px); width: 10%; height: 90%; top: 5%; }\n  .key-fa { left: calc(38% + 3px); width: 10%; height: 90%; top: 5%; }\n  .key-sol { left: calc(50% + 3px); width: 10%; height: 90%; top: 5%; }\n  .key-la { left: calc(62% + 3px); width: 10%; height: 90%; top: 5%; }\n  .key-si { left: calc(74% + 3px); width: 10%; height: 90%; top: 5%; }\n  .key-do2 { left: calc(86% + 3px); width: 10%; height: 90%; top: 5%; }\n\n  #piano-loader {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background-color: #000000;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    z-index: 100;\n    color: #33ffff;\n    font-family: Arial, sans-serif;\n    font-size: 24px;\n    font-weight: bold;\n  }\n\n  @media (max-width: 768px) {\n    #piano-loader {\n      font-size: 18px;\n    }\n  }\n<\/style>\n\n<div id=\"piano-container\">\n  <div id=\"piano-loader\">CHARGEMENT : 0%<\/div>\n  \n  <div id=\"piano-wrapper\">\n    <img decoding=\"async\" id=\"piano-image\" src=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/clavier.webp\">\n    \n    <div class=\"piano-key key-do\" data-note=\"do\" data-sound=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/1_do.mp3\"><\/div>\n    <div class=\"piano-key key-re\" data-note=\"re\" data-sound=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/2_re.mp3\"><\/div>\n    <div class=\"piano-key key-mi\" data-note=\"mi\" data-sound=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/3_mi.mp3\"><\/div>\n    <div class=\"piano-key key-fa\" data-note=\"fa\" data-sound=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/4_fa.mp3\"><\/div>\n    <div class=\"piano-key key-sol\" data-note=\"sol\" data-sound=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/5_sol.mp3\"><\/div>\n    <div class=\"piano-key key-la\" data-note=\"la\" data-sound=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/6_la.mp3\"><\/div>\n    <div class=\"piano-key key-si\" data-note=\"si\" data-sound=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/7_si.mp3\"><\/div>\n    <div class=\"piano-key key-do2\" data-note=\"do2\" data-sound=\"https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/8_do.mp3\"><\/div>\n  <\/div>\n<\/div>\n\n<script>\n  (function() {\n    'use strict';\n    \n    const loader = document.getElementById('piano-loader');\n    const keys = document.querySelectorAll('.piano-key');\n    let loadingComplete = false;\n    \n    \/\/ Timeout de s\u00e9curit\u00e9 : masque le loader apr\u00e8s 8 secondes maximum\n    \/\/ m\u00eame si tout n'est pas charg\u00e9 (\u00e9vite le blocage sur mobile)\n    const safetyTimeout = setTimeout(function() {\n      if (!loadingComplete) {\n        loadingComplete = true;\n        loader.style.display = 'none';\n        console.log('Chargement termin\u00e9 par timeout de s\u00e9curit\u00e9');\n      }\n    }, 8000);\n    \n    \/\/ Liste des ressources \u00e0 pr\u00e9charger (seulement l'image, pas les audios sur mobile)\n    const resources = [\n      'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/clavier.webp'\n    ];\n    \n    \/\/ Sur desktop, on ajoute les fichiers audio au pr\u00e9chargement\n    \/\/ Sur mobile, on les chargera \u00e0 la vol\u00e9e pour \u00e9viter le blocage\n    const isMobile = \/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini\/i.test(navigator.userAgent);\n    \n    if (!isMobile) {\n      resources.push(\n        'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/1_do.mp3',\n        'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/2_re.mp3',\n        'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/3_mi.mp3',\n        'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/4_fa.mp3',\n        'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/5_sol.mp3',\n        'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/6_la.mp3',\n        'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/7_si.mp3',\n        'https:\/\/iconoclaste.net\/blog\/wp-content\/uploads\/2026\/09\/8_do.mp3'\n      );\n    }\n    \n    let loadedCount = 0;\n    const totalResources = resources.length;\n    \n    function updateLoader() {\n      const percentage = Math.round((loadedCount \/ totalResources) * 100);\n      loader.textContent = 'CHARGEMENT : ' + percentage + '%';\n      \n      if (loadedCount >= totalResources) {\n        clearTimeout(safetyTimeout); \/\/ Annule le timeout si chargement complet\n        loadingComplete = true;\n        setTimeout(function() {\n          loader.style.display = 'none';\n        }, 300);\n      }\n    }\n    \n    function preloadResources() {\n      if (resources.length === 0) {\n        updateLoader();\n        return;\n      }\n      \n      resources.forEach(function(url) {\n        \/\/ Pr\u00e9chargement image\n        if (url.match(\/\\.(webp|jpg|jpeg|png|gif)$\/i)) {\n          const img = new Image();\n          img.onload = function() {\n            loadedCount++;\n            updateLoader();\n          };\n          img.onerror = function() {\n            loadedCount++;\n            updateLoader();\n          };\n          img.src = url;\n        } \n        \/\/ Pr\u00e9chargement audio (desktop uniquement)\n        else {\n          const audio = new Audio();\n          audio.preload = 'auto';\n          \n          \/\/ Timeout individuel pour chaque audio (3 secondes max par fichier)\n          const audioTimeout = setTimeout(function() {\n            loadedCount++;\n            updateLoader();\n          }, 3000);\n          \n          audio.oncanplaythrough = function() {\n            clearTimeout(audioTimeout);\n            loadedCount++;\n            updateLoader();\n          };\n          \n          audio.onerror = function() {\n            clearTimeout(audioTimeout);\n            loadedCount++;\n            updateLoader();\n          };\n          \n          audio.src = url;\n        }\n      });\n    }\n    \n    \/\/ Gestion des clics sur les touches\n    keys.forEach(function(key) {\n      \/\/ Support tactile et souris\n      key.addEventListener('click', function(e) {\n        e.preventDefault();\n        e.stopPropagation();\n        \n        const soundUrl = this.getAttribute('data-sound');\n        \n        \/\/ Sur mobile, cr\u00e9er un nouvel objet Audio \u00e0 chaque clic\n        \/\/ pour contourner les restrictions de lecture automatique\n        const audio = new Audio(soundUrl);\n        audio.preload = 'auto';\n        \n        \/\/ Lecture avec gestion des erreurs\n        const playPromise = audio.play();\n        \n        if (playPromise !== undefined) {\n          playPromise.catch(function(error) {\n            console.warn('Erreur lecture audio:', error);\n            \/\/ Tentative de rechargement et lecture\n            audio.load();\n            audio.play().catch(function(e) {\n              console.warn('\u00c9chec lecture:', e);\n            });\n          });\n        }\n      });\n      \n      \/\/ Support tactile am\u00e9lior\u00e9\n      key.addEventListener('touchstart', function(e) {\n        e.preventDefault(); \/\/ Emp\u00eache le double d\u00e9clenchement\n        this.click();\n      });\n    });\n    \n    \/\/ D\u00e9marrage du pr\u00e9chargement\n    if (document.readyState === 'loading') {\n      document.addEventListener('DOMContentLoaded', preloadResources);\n    } else {\n      preloadResources();\n    }\n    \n  })();\n<\/script>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>CHARGEMENT : 0%<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[269],"tags":[303,209],"class_list":["post-2060","post","type-post","status-publish","format-standard","hentry","category-experiences","tag-interactif","tag-music"],"_links":{"self":[{"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/posts\/2060","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=2060"}],"version-history":[{"count":5,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/posts\/2060\/revisions"}],"predecessor-version":[{"id":2154,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/posts\/2060\/revisions\/2154"}],"wp:attachment":[{"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/media?parent=2060"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/categories?post=2060"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/iconoclaste.net\/blog\/wp-json\/wp\/v2\/tags?post=2060"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}