Add Daylight Cycle and Candlelight CSS source types

Full-stack implementation of two new color strip source types:
- Daylight: simulates day/night color cycle with real-time or speed-based mode, latitude support
- Candlelight: multi-candle fire simulation with Gaussian falloff, layered-sine flicker, warm color shift

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 11:07:30 +03:00
parent 954e37c2ca
commit 37c80f01af
15 changed files with 882 additions and 7 deletions

View File

@@ -32,6 +32,8 @@
<option value="audio" data-i18n="color_strip.type.audio">Audio Reactive</option>
<option value="api_input" data-i18n="color_strip.type.api_input">API Input</option>
<option value="notification" data-i18n="color_strip.type.notification">Notification</option>
<option value="daylight" data-i18n="color_strip.type.daylight">Daylight Cycle</option>
<option value="candlelight" data-i18n="color_strip.type.candlelight">Candlelight</option>
</select>
</div>
@@ -534,6 +536,77 @@
</div>
</div>
<!-- Daylight Cycle section -->
<div id="css-editor-daylight-section" style="display:none">
<div id="css-editor-daylight-speed-group" class="form-group">
<div class="label-row">
<label for="css-editor-daylight-speed"><span data-i18n="color_strip.daylight.speed">Speed:</span> <span id="css-editor-daylight-speed-val">1.0</span></label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.daylight.speed.hint">Cycle speed multiplier. 1.0 = full day/night cycle in ~4 minutes. Higher values cycle faster.</small>
<input type="range" id="css-editor-daylight-speed" min="0.1" max="10" step="0.1" value="1.0"
oninput="document.getElementById('css-editor-daylight-speed-val').textContent = parseFloat(this.value).toFixed(1)">
</div>
<div class="form-group">
<div class="label-row">
<label for="css-editor-daylight-real-time" data-i18n="color_strip.daylight.use_real_time">Use Real Time:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.daylight.use_real_time.hint">When enabled, LED color matches the actual time of day. Speed is ignored.</small>
<label class="toggle-switch">
<input type="checkbox" id="css-editor-daylight-real-time" onchange="onDaylightRealTimeChange()">
<span class="toggle-slider"></span>
</label>
</div>
<div class="form-group">
<div class="label-row">
<label for="css-editor-daylight-latitude"><span data-i18n="color_strip.daylight.latitude">Latitude:</span> <span id="css-editor-daylight-latitude-val">50</span>&deg;</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.daylight.latitude.hint">Your geographic latitude (-90 to 90). Affects sunrise/sunset timing in real-time mode.</small>
<input type="range" id="css-editor-daylight-latitude" min="-90" max="90" step="1" value="50"
oninput="document.getElementById('css-editor-daylight-latitude-val').textContent = parseInt(this.value)">
</div>
</div>
<!-- Candlelight section -->
<div id="css-editor-candlelight-section" style="display:none">
<div class="form-group">
<div class="label-row">
<label for="css-editor-candlelight-color" data-i18n="color_strip.candlelight.color">Base Color:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.candlelight.color.hint">The warm base color of the candle flame. Default is a natural warm amber.</small>
<input type="color" id="css-editor-candlelight-color" value="#ff9329">
</div>
<div class="form-group">
<div class="label-row">
<label for="css-editor-candlelight-intensity"><span data-i18n="color_strip.candlelight.intensity">Flicker Intensity:</span> <span id="css-editor-candlelight-intensity-val">1.0</span></label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.candlelight.intensity.hint">How much the candles flicker. Low values = gentle glow, high values = windy candle.</small>
<input type="range" id="css-editor-candlelight-intensity" min="0.1" max="2.0" step="0.1" value="1.0"
oninput="document.getElementById('css-editor-candlelight-intensity-val').textContent = parseFloat(this.value).toFixed(1)">
</div>
<div class="form-group">
<div class="label-row">
<label for="css-editor-candlelight-num-candles" data-i18n="color_strip.candlelight.num_candles_label">Number of Candles:</label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.candlelight.num_candles.hint">How many independent candle sources along the strip. Each flickers with its own pattern. More candles = more variation.</small>
<input type="number" id="css-editor-candlelight-num-candles" min="1" max="20" step="1" value="3">
</div>
<div class="form-group">
<div class="label-row">
<label for="css-editor-candlelight-speed"><span data-i18n="color_strip.candlelight.speed">Flicker Speed:</span> <span id="css-editor-candlelight-speed-val">1.0</span></label>
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div>
<small class="input-hint" style="display:none" data-i18n="color_strip.candlelight.speed.hint">Speed of the flicker animation. Higher values produce faster, more restless flames.</small>
<input type="range" id="css-editor-candlelight-speed" min="0.1" max="5.0" step="0.1" value="1.0"
oninput="document.getElementById('css-editor-candlelight-speed-val').textContent = parseFloat(this.value).toFixed(1)">
</div>
</div>
<!-- Shared LED count field -->
<div id="css-editor-led-count-group" class="form-group">
<div class="label-row">