1/* 2 ç°å¢é³ï¼Media / 03ï¼ã 3 ãã¶ã¤ã³è¨èªã§ã¯ç´ ã® <audio> UI ã¯åºãããçµéæéã¨2pxã®ãã¼ã ãã§ç¶æ ã示ãã 4 ãã¼ã¸ã¢ã¯ã»ã¹æã«èªååçãããã©ã¦ã¶ãé³å£°ä»ãèªååçãæå¦ããå ´åã ã 5 æåã®ã¦ã¼ã¶ã¼æä½ã§åçãéå§ããï¼ãã®ããã®ãã¿ã³çã¯UIã«è¶³ããªãï¼ã 6*/ 7 8function format(seconds) { 9 const s = Math.floor(seconds || 0); 10 return String(Math.floor(s / 60)).padStart(2, '0') + ':' + String(s % 60).padStart(2, '0'); 11} 12 13function initSound(root) { 14 const audio = root.querySelector('audio'); 15 if (!audio) return; 16 17 const bar = root.querySelector('[data-progress]'); 18 const current = root.querySelector('[data-cur]'); 19 const duration = root.querySelector('[data-dur]'); 20 21 audio.addEventListener('loadedmetadata', () => { 22 if (duration) duration.textContent = format(audio.duration); 23 }); 24 25 audio.addEventListener('timeupdate', () => { 26 if (current) current.textContent = format(audio.currentTime); 27 if (bar && audio.duration) bar.style.width = (audio.currentTime / audio.duration) * 100 + '%'; 28 }); 29 30 const attempt = audio.play(); 31 if (!attempt || typeof attempt.catch !== 'function') return; 32 33 attempt.catch(() => { 34 // èªååçããããã¯ãããå ´åã®ãã©ã¼ã«ããã¯ã 35 // æåã®æä½ï¼ã¯ãªãã¯ï¼ãã¼å ¥åï¼ã¹ã¯ãã¼ã«ï¼ã§1度ã ãåçã試ã¿ãã 36 const events = ['pointerdown', 'keydown', 'scroll']; 37 const kick = () => { 38 audio.play().catch(() => {}); 39 events.forEach((name) => window.removeEventListener(name, kick)); 40 }; 41 events.forEach((name) => window.addEventListener(name, kick, { once: true, passive: true })); 42 }); 43} 44 45export function initSounds(root = document) { 46 root.querySelectorAll('.sound').forEach(initSound); 47}
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.