diff --git a/web/src/lib/components/landing/cta/cta-knot.ts b/web/src/lib/components/landing/cta/cta-knot.ts index 40545b29a..34cd0251f 100644 --- a/web/src/lib/components/landing/cta/cta-knot.ts +++ b/web/src/lib/components/landing/cta/cta-knot.ts @@ -128,10 +128,7 @@ export function slipknot(ax: number, ay: number, cinch: number, tilt: number): S const across = 0.414 * r + 4; const out: Pt = [exit[0] + h * across, exit[1] + h * across]; const reach = 8 + r * 0.6; - // Back into the knot at its lower right, heading up and left. - const into: Pt = [kx + h * r, ky + h * r]; const drop = uy - out[1]; - const rise = uy - into[1]; const loop: Pt[] = [ [ax - 6, sy], @@ -139,23 +136,29 @@ export function slipknot(ax: number, ay: number, cinch: number, tilt: number): S // Anticlockwise from the bottom (90°) round to 135°: 315° of it. ...arc(kx, ky, r, Math.PI / 2, Math.PI / 2 - (Math.PI * 7) / 4).slice(1) ]; + const near = bezier( + [out, [out[0] + h * reach, out[1] + h * reach], [lx + 2.5, uy - 0.55 * drop], [lx, uy]], + 32 + ); + const join = 9; + const [jx, jy] = near[join]; + const [nx, ny] = near[join + 1]; + const along = Math.hypot(nx - jx, ny - jy); + const lead = 0.3 * (uy - jy); + const toward: Pt = [((nx - jx) / along) * lead, ((ny - jy) / along) * lead]; + const bight: Pt[] = [exit, ...near, ...arc(ax + 22, uy, ru, Math.PI, 0).slice(1)]; const tail: Pt[] = [ - exit, - out, - ...bezier( - [out, [out[0] + h * reach, out[1] + h * reach], [lx + 2.5, uy - 0.55 * drop], [lx, uy]], - 32 - ).slice(1), - ...arc(ax + 22, uy, ru, Math.PI, 0).slice(1), + ...bight, ...bezier( [ [rx, uy], - [rx + 4, uy - 0.45 * rise], - [into[0] + 0.3 * (rx - into[0]), into[1] + 0.4 * rise], - into + [rx + 4, uy - 0.45 * (uy - jy)], + [jx + toward[0], jy + toward[1]], + [jx, jy] ], 32 - ).slice(1) + ).slice(1), + ...near.slice(2, join).reverse() ]; // Sampled finer than the rail: the loop is small, and the brush's edge is drawn // sample to sample. @@ -163,7 +166,7 @@ export function slipknot(ax: number, ay: number, cinch: number, tilt: number): S // Even to the loop's end, then heavy to the bottom of the bight and light back up: by // where along the line the loop ends and the bight bottoms out. const loopEnd = trace(loop, 1).total / line.total; - const bottom = loopEnd + ((1 - loopEnd) * (tail.length - 34)) / tail.length; + const bottom = loopEnd + ((1 - loopEnd) * bight.length) / tail.length; const ease = (t: number) => t * t * (3 - 2 * t); const weight = (s: number, total: number) => { const f = s / total;