Add smart tick labels and move direction arrows inside screen
Some checks failed
Validate / validate (push) Failing after 8s

- Add intermediate tick labels at nice intervals (5, 10, 25, 50, 100, 250, 500)
  with max 5 labels per edge and pixel-based overlap prevention
- Move direction chevrons from outside edge bars to inside the screen area
- Make chevrons filled with green fill and white outline for better contrast

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-08 05:16:17 +03:00
parent 36ace0c563
commit 57e6754461

View File

@@ -1219,12 +1219,13 @@ function renderCalibrationCanvas() {
right: ox + cW + 3, // labels right of right edge right: ox + cW + 3, // labels right of right edge
}; };
// Arrow positions (further out than tick labels) // Arrow positions (inside the screen area, near each edge bar)
const arrowInset = 12;
const arrowPos = { const arrowPos = {
top: oy - 10, top: oy + ch + arrowInset,
bottom: oy + cH + 10, bottom: oy + cH - ch - arrowInset,
left: ox - 10, left: ox + cw + arrowInset,
right: ox + cW + 10, right: ox + cW - cw - arrowInset,
}; };
// Draw ticks and direction arrows for each segment // Draw ticks and direction arrows for each segment
@@ -1235,17 +1236,55 @@ function renderCalibrationCanvas() {
const count = seg.led_count; const count = seg.led_count;
if (count === 0) return; if (count === 0) return;
// Show only first and last LED index per edge, plus LED 0 if offset > 0 // Mandatory ticks: first and last LED index per edge, plus LED 0 if offset > 0
const labelsToShow = new Set(); const labelsToShow = new Set();
labelsToShow.add(0); labelsToShow.add(0);
if (count > 1) labelsToShow.add(count - 1); if (count > 1) labelsToShow.add(count - 1);
// Add LED 0 tick on the edge where it wraps
if (offset > 0 && totalLeds > 0) { if (offset > 0 && totalLeds > 0) {
const zeroPos = (totalLeds - seg.led_start % totalLeds) % totalLeds; const zeroPos = (totalLeds - seg.led_start % totalLeds) % totalLeds;
if (zeroPos < count) labelsToShow.add(zeroPos); if (zeroPos < count) labelsToShow.add(zeroPos);
} }
// Add intermediate ticks at "nice" intervals (max 5 labels per edge)
if (count > 2) {
const edgeLen = geo.horizontal ? (geo.x2 - geo.x1) : (geo.y2 - geo.y1);
const maxDigits = String(totalLeds > 0 ? totalLeds - 1 : count - 1).length;
const minSpacing = geo.horizontal ? maxDigits * 7 + 8 : 22;
const maxIntermediate = Math.max(0, 5 - labelsToShow.size);
const niceSteps = [5, 10, 25, 50, 100, 250, 500];
let step = niceSteps[niceSteps.length - 1];
for (const s of niceSteps) {
if (Math.floor(count / s) <= maxIntermediate) {
step = s;
break;
}
}
// Pixel position helper (0..edgeLen along the edge)
const tickPx = i => {
const f = i / (count - 1);
return (seg.reverse ? (1 - f) : f) * edgeLen;
};
// Collect pixel positions of mandatory ticks
const placed = [];
labelsToShow.forEach(i => placed.push(tickPx(i)));
// Add ticks at LED indices divisible by step
for (let i = 1; i < count - 1; i++) {
const idx = totalLeds > 0 ? (seg.led_start + i) % totalLeds : seg.led_start + i;
if (idx % step === 0) {
const px = tickPx(i);
if (!placed.some(p => Math.abs(px - p) < minSpacing)) {
labelsToShow.add(i);
placed.push(px);
}
}
}
}
// Tick styling // Tick styling
const tickLen = 5; const tickLen = 5;
ctx.strokeStyle = 'rgba(255, 255, 255, 0.4)'; ctx.strokeStyle = 'rgba(255, 255, 255, 0.4)';
@@ -1291,8 +1330,8 @@ function renderCalibrationCanvas() {
} }
}); });
// Draw direction chevron at midpoint, outside the edge bar // Draw direction chevron at midpoint, inside the screen area
const s = 5; const s = 7;
let mx, my, angle; let mx, my, angle;
if (geo.horizontal) { if (geo.horizontal) {
mx = (geo.x1 + geo.x2) / 2; mx = (geo.x1 + geo.x2) / 2;
@@ -1307,14 +1346,17 @@ function renderCalibrationCanvas() {
ctx.save(); ctx.save();
ctx.translate(mx, my); ctx.translate(mx, my);
ctx.rotate(angle); ctx.rotate(angle);
ctx.strokeStyle = '#4CAF50'; ctx.fillStyle = 'rgba(76, 175, 80, 0.85)';
ctx.lineWidth = 1.5; ctx.strokeStyle = 'rgba(255, 255, 255, 0.6)';
ctx.lineWidth = 1;
ctx.lineCap = 'round'; ctx.lineCap = 'round';
ctx.lineJoin = 'round'; ctx.lineJoin = 'round';
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(-s * 0.4, -s * 0.5); ctx.moveTo(-s * 0.5, -s * 0.6);
ctx.lineTo(s * 0.4, 0); ctx.lineTo(s * 0.5, 0);
ctx.lineTo(-s * 0.4, s * 0.5); ctx.lineTo(-s * 0.5, s * 0.6);
ctx.closePath();
ctx.fill();
ctx.stroke(); ctx.stroke();
ctx.restore(); ctx.restore();
}); });