Spaces:
Sleeping
Sleeping
File size: 1,823 Bytes
eddc354 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import type { ElementKind } from "@/lib/tatting";
type Props = {
kind: ElementKind;
picots: number;
radius: number;
color: string;
};
const r3 = (n: number) => Math.round(n * 1000) / 1000;
/** Renders a tatting motif centered at (0,0) in local coordinates. */
export function Shape({ kind, picots, radius, color }: Props) {
const picotR = Math.max(3, radius * 0.11);
if (kind === "ring") {
const dots = Array.from({ length: picots }, (_, i) => {
const a = (i / picots) * Math.PI * 2 - Math.PI / 2;
return {
cx: r3(Math.cos(a) * (radius + picotR * 0.7)),
cy: r3(Math.sin(a) * (radius + picotR * 0.7)),
};
});
return (
<g fill="none" stroke={color} strokeWidth={2.5} strokeLinecap="round">
<circle cx={0} cy={0} r={radius} />
<circle cx={0} cy={0} r={radius - 5} strokeWidth={1} opacity={0.45} />
{dots.map((d, i) => (
<circle key={i} cx={d.cx} cy={d.cy} r={picotR} />
))}
</g>
);
}
// Arc: half-circle bow with picots along the outer edge
const start = { x: -radius, y: 0 };
const end = { x: radius, y: 0 };
const dots = Array.from({ length: picots }, (_, i) => {
const t = (i + 1) / (picots + 1);
const a = Math.PI - t * Math.PI;
const rr = radius + picotR * 0.7;
return { cx: r3(Math.cos(a) * rr), cy: r3(-Math.sin(a) * rr) };
});
return (
<g fill="none" stroke={color} strokeWidth={2.5} strokeLinecap="round">
<path d={`M ${start.x} ${start.y} A ${radius} ${radius} 0 0 1 ${end.x} ${end.y}`} />
<path
d={`M ${start.x + 5} 0 A ${radius - 5} ${radius - 5} 0 0 1 ${end.x - 5} 0`}
strokeWidth={1}
opacity={0.45}
/>
{dots.map((d, i) => (
<circle key={i} cx={d.cx} cy={d.cy} r={picotR} />
))}
</g>
);
}
|