diff --git a/server/src/wled_controller/static/app.js b/server/src/wled_controller/static/app.js index 29b90f0..ab54e4a 100644 --- a/server/src/wled_controller/static/app.js +++ b/server/src/wled_controller/static/app.js @@ -1092,6 +1092,15 @@ async function showCalibration(deviceId) { initSpanDrag(); requestAnimationFrame(() => renderCalibrationCanvas()); + // Re-render on container resize (e.g. window resize changes aspect-ratio container) + if (!window._calibrationResizeObserver) { + window._calibrationResizeObserver = new ResizeObserver(() => { + updateSpanBars(); + renderCalibrationCanvas(); + }); + } + window._calibrationResizeObserver.observe(preview); + } catch (error) { console.error('Failed to load calibration:', error); showToast('Failed to load calibration', 'error'); @@ -1116,6 +1125,9 @@ function forceCloseCalibrationModal() { if (deviceId) { clearTestMode(deviceId); } + if (window._calibrationResizeObserver) { + window._calibrationResizeObserver.disconnect(); + } const modal = document.getElementById('calibration-modal'); const error = document.getElementById('calibration-error'); modal.style.display = 'none'; @@ -1198,9 +1210,9 @@ function renderCalibrationCanvas() { const containerRect = container.getBoundingClientRect(); if (containerRect.width === 0 || containerRect.height === 0) return; - // Canvas extends beyond the container (matches CSS: left:-36px, top:-36px, +72px/+72px) - const padX = 36; - const padY = 36; + // Canvas extends beyond the container (matches CSS: left:-40px, top:-40px, +80px/+80px) + const padX = 40; + const padY = 40; const dpr = window.devicePixelRatio || 1; const canvasW = containerRect.width + padX * 2; @@ -1259,8 +1271,8 @@ function renderCalibrationCanvas() { right: { y1: oy + ch + (spans.right?.start || 0) * edgeLenV, y2: oy + ch + (spans.right?.end || 1) * edgeLenV, midX: ox + cW - cw / 2, horizontal: false }, }; - // Axis positions for labels (outside the 12px toggle zones) - const toggleSize = 12; + // Axis positions for labels (outside the 16px toggle zones) + const toggleSize = 16; const axisPos = { top: oy - toggleSize - 3, bottom: oy + cH + toggleSize + 3, @@ -1334,8 +1346,9 @@ function renderCalibrationCanvas() { } } - // Tick styling - const tickLen = 5; + // Tick styling — min/max ticks extend to container border, others short + const tickLenLong = toggleSize + 3; + const tickLenShort = 4; ctx.strokeStyle = tickStroke; ctx.lineWidth = 1; ctx.fillStyle = tickFill; @@ -1345,6 +1358,7 @@ function renderCalibrationCanvas() { const fraction = count > 1 ? i / (count - 1) : 0.5; const displayFraction = seg.reverse ? (1 - fraction) : fraction; const ledIndex = totalLeds > 0 ? (seg.led_start + i) % totalLeds : seg.led_start + i; + const tickLen = (i === 0 || i === count - 1) ? tickLenLong : tickLenShort; if (geo.horizontal) { const tx = geo.x1 + displayFraction * (geo.x2 - geo.x1); @@ -1379,16 +1393,16 @@ function renderCalibrationCanvas() { } }); - // Draw direction chevron at midpoint, inside the screen area + // Draw direction chevron at full-edge midpoint (not affected by span) const s = 7; let mx, my, angle; if (geo.horizontal) { - mx = (geo.x1 + geo.x2) / 2; + mx = ox + cw + edgeLenH / 2; my = arrowPos[seg.edge]; angle = seg.reverse ? Math.PI : 0; } else { mx = arrowPos[seg.edge]; - my = (geo.y1 + geo.y2) / 2; + my = oy + ch + edgeLenV / 2; angle = seg.reverse ? -Math.PI / 2 : Math.PI / 2; } @@ -1414,6 +1428,7 @@ function renderCalibrationCanvas() { function updateSpanBars() { const spans = window.edgeSpans || {}; + const container = document.querySelector('.calibration-preview'); ['top', 'right', 'bottom', 'left'].forEach(edge => { const bar = document.querySelector(`.edge-span-bar[data-edge="${edge}"]`); if (!bar) return; @@ -1430,6 +1445,24 @@ function updateSpanBars() { bar.style.top = (span.start * totalHeight) + 'px'; bar.style.height = ((span.end - span.start) * totalHeight) + 'px'; } + + // Also reposition toggle zone to match span region + if (!container) return; + const toggle = container.querySelector(`.toggle-${edge}`); + if (!toggle) return; + if (isHorizontal) { + const cornerW = 56; + const edgeW = container.clientWidth - 2 * cornerW; + toggle.style.left = (cornerW + span.start * edgeW) + 'px'; + toggle.style.right = 'auto'; + toggle.style.width = ((span.end - span.start) * edgeW) + 'px'; + } else { + const cornerH = 36; + const edgeH = container.clientHeight - 2 * cornerH; + toggle.style.top = (cornerH + span.start * edgeH) + 'px'; + toggle.style.bottom = 'auto'; + toggle.style.height = ((span.end - span.start) * edgeH) + 'px'; + } }); } @@ -1537,6 +1570,11 @@ function setStartPosition(position) { updateCalibrationPreview(); } +function toggleEdgeInputs() { + const preview = document.querySelector('.calibration-preview'); + if (preview) preview.classList.toggle('inputs-dimmed'); +} + function toggleDirection() { const select = document.getElementById('cal-layout'); select.value = select.value === 'clockwise' ? 'counterclockwise' : 'clockwise'; diff --git a/server/src/wled_controller/static/index.html b/server/src/wled_controller/static/index.html index 0ea4dbb..7b1a8c7 100644 --- a/server/src/wled_controller/static/index.html +++ b/server/src/wled_controller/static/index.html @@ -80,15 +80,17 @@ @@ -224,6 +226,7 @@ @@ -261,6 +264,7 @@