test
This commit is contained in:
1 parent
0c2b4e7df2
commit
e652b54319
11 files changed
+202
-12
No files matched your search
@@ -13,7 +13,21 @@ const { kind, class: className } = Astro.props;
|
||||
|
||||
const S = 400;
|
||||
const f = (n: number) => Math.round(n * 10) / 10;
|
||||
const poly = (pts: [number, number][]) => pts.map(([x, y]) => `${f(x)},${f(y)}`).join(' ');
|
||||
|
||||
/* Every drawing is laid out by hand, so the box is derived from the geometry rather than
|
||||
assumed: each point is recorded as it is emitted and the viewBox follows at the end. That
|
||||
way a drawing can never be clipped, whatever a new kind does. */
|
||||
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
||||
const track = (x: number, y: number) => {
|
||||
if (x < minX) minX = x;
|
||||
if (x > maxX) maxX = x;
|
||||
if (y < minY) minY = y;
|
||||
if (y > maxY) maxY = y;
|
||||
};
|
||||
const poly = (pts: [number, number][]) => {
|
||||
for (const [x, y] of pts) track(x, y);
|
||||
return pts.map(([x, y]) => `${f(x)},${f(y)}`).join(' ');
|
||||
};
|
||||
|
||||
/* Isometric projection of a 3D point (x right, y up, z towards the viewer's left). */
|
||||
const ISO = { cx: S / 2, cy: S / 2, c30: Math.cos(Math.PI / 6), s30: Math.sin(Math.PI / 6) };
|
||||
@@ -65,6 +79,8 @@ if (kind === 'sphere') {
|
||||
lines.push(poly(pts));
|
||||
}
|
||||
lines.push(`circle:${R}`);
|
||||
track(ISO.cx - R, ISO.cy - R);
|
||||
track(ISO.cx + R, ISO.cy + R);
|
||||
}
|
||||
|
||||
if (kind === 'cube') {
|
||||
@@ -138,12 +154,17 @@ if (kind === 'stack') {
|
||||
for (let k = 0; k < layers; k++) plane(n, u, k * gapY, cy).forEach((l) => lines.push(l));
|
||||
const corners: [number, number][] = [[0, 0], [L, 0], [L, L], [0, L]];
|
||||
corners.forEach(([x, z]) => lines.push(poly([iso(x, 0, z, cy), iso(x, (layers - 1) * gapY, z, cy)])));
|
||||
// shift the whole drawing so the isometric footprint sits centred
|
||||
const dx = -((L - L) * ISO.c30) / 2;
|
||||
void dx;
|
||||
}
|
||||
/* A square box centred on the drawing: wide drawings still fill the width, and every object
|
||||
keeps the same footprint, so the four cards of a row stay even. The padding covers the
|
||||
stroke, which sits half outside the geometry. */
|
||||
const PAD = 8;
|
||||
const width = maxX - minX;
|
||||
const height = maxY - minY;
|
||||
const side = Math.max(width, height) + PAD * 2;
|
||||
const viewBox = [minX + width / 2 - side / 2, minY + height / 2 - side / 2, side, side].map(f).join(' ');
|
||||
---
|
||||
<svg class:list={['grid-object', className]} viewBox={`0 0 ${S} ${S}`} aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg class:list={['grid-object', className]} viewBox={viewBox} aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" stroke="currentColor" stroke-width="1.25" stroke-linejoin="round" stroke-linecap="round" vector-effect="non-scaling-stroke">
|
||||
{lines.map((l) => l.startsWith('circle:')
|
||||
? <circle cx={S / 2} cy={S / 2} r={Number(l.slice(7))} />
|
||||
|
||||
Reference in new issue
Block a user