Add animation effects + double-buffered FPS optimization

- Add 5 new animation effects (strobe, sparkle, pulse, candle, rainbow
  fade) to both static and gradient color strip streams
- Fix FPS drops (30→25) by using 5ms re-poll on frame skip instead of
  full frame_time, preventing synchronization misses between animation
  thread and processing loop
- Double-buffer animation output arrays to eliminate per-frame numpy
  allocations and reduce GC pressure
- Use uint16 integer math for gradient brightness scaling instead of
  float32 intermediates
- Update animation type dropdowns and locale strings (en + ru)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-21 01:57:43 +03:00
parent 84f063eee9
commit 55a9662234
5 changed files with 220 additions and 25 deletions

View File

@@ -57,13 +57,23 @@ export function onCSSTypeChange() {
if (type === 'static') {
animSection.style.display = '';
animTypeSelect.innerHTML =
`<option value="breathing">${t('color_strip.animation.type.breathing')}</option>`;
`<option value="breathing">${t('color_strip.animation.type.breathing')}</option>` +
`<option value="strobe">${t('color_strip.animation.type.strobe')}</option>` +
`<option value="sparkle">${t('color_strip.animation.type.sparkle')}</option>` +
`<option value="pulse">${t('color_strip.animation.type.pulse')}</option>` +
`<option value="candle">${t('color_strip.animation.type.candle')}</option>` +
`<option value="rainbow_fade">${t('color_strip.animation.type.rainbow_fade')}</option>`;
} else if (type === 'gradient') {
animSection.style.display = '';
animTypeSelect.innerHTML =
`<option value="breathing">${t('color_strip.animation.type.breathing')}</option>` +
`<option value="gradient_shift">${t('color_strip.animation.type.gradient_shift')}</option>` +
`<option value="wave">${t('color_strip.animation.type.wave')}</option>`;
`<option value="wave">${t('color_strip.animation.type.wave')}</option>` +
`<option value="strobe">${t('color_strip.animation.type.strobe')}</option>` +
`<option value="sparkle">${t('color_strip.animation.type.sparkle')}</option>` +
`<option value="pulse">${t('color_strip.animation.type.pulse')}</option>` +
`<option value="candle">${t('color_strip.animation.type.candle')}</option>` +
`<option value="rainbow_fade">${t('color_strip.animation.type.rainbow_fade')}</option>`;
} else {
animSection.style.display = 'none';
}

View File

@@ -596,11 +596,16 @@
"color_strip.animation.enabled": "Enable Animation:",
"color_strip.animation.enabled.hint": "Enables procedural animation. The LEDs will update at 30 fps driven by the selected effect.",
"color_strip.animation.type": "Effect:",
"color_strip.animation.type.hint": "The animation effect to apply. Breathing works for both static and gradient sources; Gradient Shift and Wave work for gradient sources only.",
"color_strip.animation.type.hint": "The animation effect to apply. Breathing, Strobe, Sparkle, Pulse, Candle, and Rainbow Fade work for both static and gradient sources; Gradient Shift and Wave are gradient-only.",
"color_strip.animation.type.breathing": "Breathing",
"color_strip.animation.type.color_cycle": "Color Cycle",
"color_strip.animation.type.gradient_shift": "Gradient Shift",
"color_strip.animation.type.wave": "Wave",
"color_strip.animation.type.strobe": "Strobe",
"color_strip.animation.type.sparkle": "Sparkle",
"color_strip.animation.type.pulse": "Pulse",
"color_strip.animation.type.candle": "Candle",
"color_strip.animation.type.rainbow_fade": "Rainbow Fade",
"color_strip.animation.speed": "Speed:",
"color_strip.animation.speed.hint": "Animation speed multiplier. 1.0 ≈ one cycle per second for Breathing; higher values cycle faster.",
"color_strip.color_cycle.colors": "Colors:",

View File

@@ -596,11 +596,16 @@
"color_strip.animation.enabled": "Включить анимацию:",
"color_strip.animation.enabled.hint": "Включает процедурную анимацию. Светодиоды обновляются со скоростью 30 кадров в секунду по выбранному эффекту.",
"color_strip.animation.type": "Эффект:",
"color_strip.animation.type.hint": "Эффект анимации. Дыхание работает для статичного цвета и градиента; сдвиг градиента и волна — только для градиентных источников.",
"color_strip.animation.type.hint": "Эффект анимации. Дыхание, стробоскоп, искры, пульс, свеча и радужный перелив работают для статического цвета и градиента; сдвиг градиента и волна — только для градиентов.",
"color_strip.animation.type.breathing": "Дыхание",
"color_strip.animation.type.color_cycle": "Смена цвета",
"color_strip.animation.type.gradient_shift": "Сдвиг градиента",
"color_strip.animation.type.wave": "Волна",
"color_strip.animation.type.strobe": "Стробоскоп",
"color_strip.animation.type.sparkle": "Искры",
"color_strip.animation.type.pulse": "Пульс",
"color_strip.animation.type.candle": "Свеча",
"color_strip.animation.type.rainbow_fade": "Радужный перелив",
"color_strip.animation.speed": "Скорость:",
"color_strip.animation.speed.hint": "Множитель скорости анимации. 1.0 ≈ один цикл в секунду для дыхания; большие значения ускоряют анимацию.",
"color_strip.color_cycle.colors": "Цвета:",