Scale fire flames with SVG transform anchored at base, floor at 1200W
Replace clip-rect height manipulation with translate-scale-translate SVG transform on fire-group, pivoting at the fixed base coordinate y=248. Eliminates base-hopping caused by fill-box bounding-box drift from individual flame flicker animations. Clip rect is now static (guards against flicker overshoot above the pot bottom). Minimum visible flame size floored at the scale corresponding to 1200W. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JLR2133M2PyjiYq584i2G7
This commit is contained in:
+6
-12
@@ -295,23 +295,17 @@ function updateStirrerVisualization() {
|
|||||||
// --- Fire visualization ---
|
// --- Fire visualization ---
|
||||||
|
|
||||||
function updateFireVisualization() {
|
function updateFireVisualization() {
|
||||||
const g = document.getElementById('fire-group');
|
const g = document.getElementById('fire-group');
|
||||||
const clipRect = document.getElementById('fire-clip-rect');
|
|
||||||
if (!g) return;
|
if (!g) return;
|
||||||
const fireBase = 248; // y of flame base (all paths end here)
|
|
||||||
const fireTip = 177; // y of tallest flame tip
|
|
||||||
const fireH = fireBase - fireTip; // 71px total flame height
|
|
||||||
if (heaterPowerSoll <= 0) {
|
if (heaterPowerSoll <= 0) {
|
||||||
g.style.opacity = '0';
|
g.style.opacity = '0';
|
||||||
clipRect.setAttribute('height', '0');
|
g.removeAttribute('transform');
|
||||||
} else {
|
} else {
|
||||||
const intensity = Math.min(1, heaterPowerSoll / heaterMaxPower);
|
const intensity = Math.min(1, heaterPowerSoll / heaterMaxPower);
|
||||||
// Always show the lower 35% (base), scale upper 65% with intensity
|
const minScale = 1200 / heaterMaxPower;
|
||||||
const visibleH = (0.35 + 0.65 * intensity) * fireH;
|
const scale = Math.max(minScale, intensity);
|
||||||
const topBuffer = 20; // headroom for flicker scaleY overshoot (~12% of height)
|
g.style.opacity = '1';
|
||||||
clipRect.setAttribute('y', (fireBase - visibleH - topBuffer).toFixed(1));
|
g.setAttribute('transform', `translate(0,248) scale(1,${scale.toFixed(3)}) translate(0,-248)`);
|
||||||
clipRect.setAttribute('height', (visibleH + topBuffer + 2).toFixed(1));
|
|
||||||
g.style.opacity = String((0.6 + 0.4 * intensity).toFixed(2));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@
|
|||||||
<rect id="water-clip-rect" x="63" y="172" width="114" height="0"/>
|
<rect id="water-clip-rect" x="63" y="172" width="114" height="0"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<clipPath id="fire-clip">
|
<clipPath id="fire-clip">
|
||||||
<rect id="fire-clip-rect" x="60" y="248" width="130" height="0"/>
|
<rect x="55" y="175" width="140" height="78"/>
|
||||||
</clipPath>
|
</clipPath>
|
||||||
<!-- Flame gradients: solid at base (y=1), transparent at tip (y=0) -->
|
<!-- Flame gradients: solid at base (y=1), transparent at tip (y=0) -->
|
||||||
<linearGradient id="fg-red" x1="0" y1="1" x2="0" y2="0">
|
<linearGradient id="fg-red" x1="0" y1="1" x2="0" y2="0">
|
||||||
|
|||||||
Reference in New Issue
Block a user