diff --git a/web/app.js b/web/app.js index 91d953e..e2be24d 100644 --- a/web/app.js +++ b/web/app.js @@ -273,6 +273,20 @@ function updateStepPlates() { }); } +// --- Stirrer visualization --- + +function updateStirrerVisualization() { + const g = document.getElementById('stirrer-blades'); + if (!g) return; + if (stirrerSpeedIst > 0) { + const duration = Math.min(10, 50 / stirrerSpeedIst).toFixed(2); + g.style.setProperty('--stir-duration', duration + 's'); + g.classList.add('spinning'); + } else { + g.classList.remove('spinning'); + } +} + // --- Fire visualization --- function updateFireVisualization() { @@ -487,6 +501,7 @@ function onStirrerChanged(msg) { document.getElementById('stirrer-speed-readout').textContent = msg.Speed; initialSpeedSync = false; } + updateStirrerVisualization(); updateStepPlates(); } else if (key === 'Capabilities') { const power = msg.Capabilities.Power; diff --git a/web/index.html b/web/index.html index 2a2597f..eb28921 100644 --- a/web/index.html +++ b/web/index.html @@ -100,8 +100,10 @@ - - + + + + diff --git a/web/style.css b/web/style.css index aa0f207..582ee72 100644 --- a/web/style.css +++ b/web/style.css @@ -152,6 +152,19 @@ header#connection-bar { display: block; } +/* Stirrer animation */ +@keyframes stir-rotate { + to { transform: rotate(360deg); } +} +#stirrer-blades { + transform-box: fill-box; + transform-origin: 50% 50%; + animation: stir-rotate var(--stir-duration, 1s) linear infinite paused; +} +#stirrer-blades.spinning { + animation-play-state: running; +} + /* Fire animations */ @keyframes flicker-1 { 0%, 100% { transform: scaleY(1.00) scaleX(1.00); }