sandbox/studio: fix amber arc clipping at the canvas edges

The amber arc was drawn at radius ~30px from center on a 56×56
canvas — the bottom of the arc (at angles near 6 o'clock) sat at
y ≈ 58 and got clipped by the canvas's own bounding box. Visible
as a flat cut-off at extreme positions.

Fix: bump the canvas to 72×72 and use fixed-pixel values for the
knob's geometry instead of fractions of `size`, so the visible knob
diameter stays at ~52px regardless of canvas size and there's now
~10px of margin all around for the arc and drop shadow.

- KNOB_SIZE: 56 → 72
- totalR: size * 0.46 → 26 (fixed)
- rimW:   size * 0.045 → 2.5 (fixed)
- notch half-base: size * 0.026 → 1.5 (fixed)
- cy: size/2 + 1 → size/2 (no need for the offset on the larger canvas)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jose Luis Montañes
2026-05-01 18:22:34 +02:00
parent f163a24f62
commit 2193409b6e

View File

@@ -575,7 +575,9 @@ for (const line of PATCH) {
// knob — restrained: dark gradient + thin amber arc + single tickmark. // knob — restrained: dark gradient + thin amber arc + single tickmark.
// No knurled ridges, no brushed metal. Closer to the reference image. // No knurled ridges, no brushed metal. Closer to the reference image.
// =========================================================================== // ===========================================================================
const KNOB_SIZE = 56; // Canvas is bigger than the visible knob so the amber arc + drop shadow have
// room around the dial. Visible knob radius is ~26px regardless of canvas size.
const KNOB_SIZE = 72;
function setupCanvas(canvas, size) { function setupCanvas(canvas, size) {
const dpr = window.devicePixelRatio || 1; const dpr = window.devicePixelRatio || 1;
canvas.style.width = size + 'px'; canvas.style.width = size + 'px';
@@ -588,10 +590,12 @@ function setupCanvas(canvas, size) {
} }
function drawKnob(ctx, size, norm) { function drawKnob(ctx, size, norm) {
const cx = size / 2, cy = size / 2 + 1; const cx = size / 2, cy = size / 2;
const totalR = size * 0.46; // outer edge of the whole knob // Fixed pixel sizes so the visible knob doesn't grow with the canvas.
const rimW = size * 0.045; // dark rim thickness (thin) // Canvas size only adds margin around these for arc + shadow.
const discR = totalR - rimW; // metallic disc fills most of inside const totalR = 26; // outer edge of the whole knob
const rimW = 2.5; // dark rim thickness
const discR = totalR - rimW; // metallic disc fills most of inside
ctx.clearRect(0, 0, size, size); ctx.clearRect(0, 0, size, size);
// (1) drop shadow under the whole knob // (1) drop shadow under the whole knob
@@ -723,7 +727,7 @@ function drawKnob(ctx, size, norm) {
const tipR = discR * 0.86; const tipR = discR * 0.86;
const baseR = discR * 0.50; const baseR = discR * 0.50;
const perp = ang + Math.PI / 2; const perp = ang + Math.PI / 2;
const half = size * 0.026; const half = 1.5; // fixed half-width of the notch base
const tipX = cx + Math.cos(ang) * tipR; const tipX = cx + Math.cos(ang) * tipR;
const tipY = cy + Math.sin(ang) * tipR; const tipY = cy + Math.sin(ang) * tipR;
const bX = cx + Math.cos(ang) * baseR; const bX = cx + Math.cos(ang) * baseR;