Lub Dub Valves Review
// ensure audio context is unlocked on first user click anywhere const unlockAudio = () => if (audioCtx.state === 'suspended') audioCtx.resume(); document.removeEventListener('click', unlockAudio); document.removeEventListener('touchstart', unlockAudio); ; document.addEventListener('click', unlockAudio); document.addEventListener('touchstart', unlockAudio);
// individual buttons document.getElementById('playLubBtn').addEventListener('click', () => if (autoInterval) stopAutoCycle(); playLub(); activateLub(); statusSpan.innerHTML = '🔊 Manual LUB (AV valves)'; setTimeout(() => if (!autoInterval) statusSpan.innerHTML = '⚡ idle'; , 800); );
function stopAutoCycle() if (autoInterval) clearInterval(autoInterval); autoInterval = null; isAuto = false; statusSpan.innerHTML = '⚡ idle'; lub dub valves
.lub .valve-title color: #ff9f7c; .dub .valve-title color: #7cd4ff;
// ----- Animation & Valve Activation ----- const lubValveDiv = document.getElementById('lubValve'); const dubValveDiv = document.getElementById('dubValve'); const statusSpan = document.getElementById('statusMsg'); // ensure audio context is unlocked on first
.valve-desc font-size: 0.85rem; color: #bbd4f0;
footer text-align: center; font-size: 0.7rem; margin-top: 1.5rem; opacity: 0.7; </style> </head> <body> <div class="card"> <h1>❤️ LUB DUB VALVES</h1> <div class="sub">atrioventricular → lub | semilunar → dub</div> if (audioCtx.state === 'suspended') audioCtx.resume()
function getCycleIntervalMs() const bpm = parseInt(bpmSlider.value, 10); // one cardiac cycle = 60/BPM seconds → milliseconds return (60 / bpm) * 1000;