From b98fe575b0d20cc8a97f6ab1594a853d9bf91b01 Mon Sep 17 00:00:00 2001 From: Override-6 Date: Sun, 10 Dec 2023 15:41:28 +0100 Subject: [PATCH] add start/end radius --- front/components/arrows/BendableArrow.tsx | 21 +++++++++++++++++---- front/components/arrows/Pos.ts | 5 +++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/front/components/arrows/BendableArrow.tsx b/front/components/arrows/BendableArrow.tsx index 33540fd..2374251 100644 --- a/front/components/arrows/BendableArrow.tsx +++ b/front/components/arrows/BendableArrow.tsx @@ -1,5 +1,5 @@ import { CSSProperties, ReactElement, useCallback, useEffect, useRef } from "react" -import { add, Pos, relativeTo, size } from "./Pos" +import { add, angle, Pos, relativeTo, size } from "./Pos" export interface BendableArrowProps { basePos: Pos @@ -24,6 +24,15 @@ const ArrowStyleDefaults = { width: 4 } +function constraintInCircle(pos: Pos, from: Pos, radius: number): Pos { + const theta = angle(pos, from) + + return { + x: pos.x - Math.sin(theta) * radius, + y: pos.y - Math.cos(theta) * radius + } +} + export default function BendableArrow({ basePos, startPos, endPos, style, startRadius = 0, endRadius = 0 }: BendableArrowProps) { const svgRef = useRef(null) @@ -36,11 +45,15 @@ export default function BendableArrow({ basePos, startPos, endPos, style, startR const startRelative = relativeTo(startPos, basePos) const endRelative = relativeTo(endPos, basePos) + const tailPos = constraintInCircle(startRelative, endRelative, startRadius) + const headPos = constraintInCircle(endRelative, startRelative, endRadius) + + // the width and height of the arrow svg const svgBoxBounds = size(startPos, endPos) - const left = Math.min(startRelative.x, endRelative.x) - const top = Math.min(startRelative.y, endRelative.y) + const left = Math.min(tailPos.x, headPos.x) + const top = Math.min(tailPos.y, headPos.y) const svgStyle: CSSProperties = { @@ -52,7 +65,7 @@ export default function BendableArrow({ basePos, startPos, endPos, style, startR } - const d = `M${startRelative.x - left} ${startRelative.y - top} L${endRelative.x - left} ${endRelative.y - top}` + const d = `M${tailPos.x - left} ${tailPos.y - top} L${headPos.x - left} ${headPos.y - top}` pathRef.current!.setAttribute("d", d) Object.assign(svgRef.current!.style, svgStyle) diff --git a/front/components/arrows/Pos.ts b/front/components/arrows/Pos.ts index 107aee2..0d3aa9c 100644 --- a/front/components/arrows/Pos.ts +++ b/front/components/arrows/Pos.ts @@ -34,3 +34,8 @@ export function size(a: Pos, b: Pos): Pos { export function add(a: Pos, b: Pos): Pos { return { x: a.x + b.x, y: a.y + b.y } } + +export function angle(a: Pos, b: Pos): number { + const r = relativeTo(a, b) + return Math.atan2(r.x, r.y) +} \ No newline at end of file