diff --git a/apps/web/src/components/story/threadPath.ts b/apps/web/src/components/story/threadPath.ts index 051e30e..5c771b9 100644 --- a/apps/web/src/components/story/threadPath.ts +++ b/apps/web/src/components/story/threadPath.ts @@ -72,6 +72,8 @@ const POLYGONS: Readonly, readonly Point[]>> = }; const CORNER = 36; +/** How far above its end the trace crosses the page when it comes from the other side. */ +const END_DROP = 64; const round = (value: number): number => Math.round(value * 10) / 10; /** The figure as path commands. `direction` is 1 when the line arrives heading right, -1 heading left. */ @@ -134,8 +136,20 @@ export const threadPath = (thread: { if (thread.end) { const [x, y] = thread.end; - const bend = Math.abs(x - side); - d += `L${side} ${round(y - bend)}L${round(x)} ${round(y)}`; + const away = Math.abs(x - side); + if (away <= 2 * CORNER) { + // The end is beside the margin the trace is in: one bend leads to it. + d += `L${side} ${round(y - away)}L${round(x)} ${round(y)}`; + } else { + // The end is on the other side: cross the page above it, then come + // straight down to it, beside the text. One long diagonal instead would start far up the page. + const inward = x < side ? -1 : 1; + const across = round(y - END_DROP); + d += + `L${side} ${across - CORNER}L${side + inward * CORNER} ${across}` + + `L${round(x - inward * CORNER)} ${across}L${round(x)} ${across + CORNER}L${round(x)} ${round(y)}`; + pads.push([side, across - CORNER]); + } pads.push([round(x), round(y)]); } return { d, pads };