Skip to content

Commit 9b18098

Browse files
authored
feat: draw L shaped arrows for Knight moves (#208)
1 parent 9f3751c commit 9b18098

File tree

1 file changed

+58
-17
lines changed

1 file changed

+58
-17
lines changed

src/Arrows.tsx

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,61 @@ export function Arrows() {
9292
// This gives us the length of the arrow if it went from center to center
9393
const r = Math.hypot(dy, dx);
9494

95-
// Calculate the new end point for the arrow
96-
// We subtract ARROW_LENGTH_REDUCER from the total distance to make the arrow
97-
// stop before reaching the center of the target square
98-
const end = {
99-
// Calculate new end x coordinate by:
100-
// 1. Taking the original x direction (dx)
101-
// 2. Scaling it by (r - ARROW_LENGTH_REDUCER) / r to shorten it
102-
// 3. Adding to the starting x coordinate
103-
x: from.x + (dx * (r - ARROW_LENGTH_REDUCER)) / r,
104-
// Same calculation for y coordinate
105-
y: from.y + (dy * (r - ARROW_LENGTH_REDUCER)) / r,
106-
};
95+
let pathD: string;
96+
97+
// Is Knight move
98+
if (r === Math.hypot(1, 2) * squareWidth) {
99+
// The mid point is only used in Knight move drawing
100+
// and here we prioritise drawing along the long edge
101+
// by defining the midpoint depending on which is bigger X or Y
102+
const mid =
103+
Math.abs(dx) < Math.abs(dy)
104+
? {
105+
x: from.x,
106+
y: to.y,
107+
}
108+
: {
109+
x: to.x,
110+
y: from.y,
111+
};
112+
113+
// Calculate the difference in x and y coordinates between mid and end points
114+
const dxEnd = to.x - mid.x;
115+
const dyEnd = to.y - mid.y;
116+
117+
// End arrow distance is always one squareWidth for Knight moves
118+
const rEnd = squareWidth;
119+
120+
// Calculate the new end point for the arrow
121+
// We subtract ARROW_LENGTH_REDUCER from the end line distance to make the arrow
122+
// stop before reaching the center of the target square
123+
const end = {
124+
// Calculate new end x coordinate by:
125+
// 1. Taking the mid->end x direction (dxEnd)
126+
// 2. Scaling it by (rEnd - ARROW_LENGTH_REDUCER) / rEnd to shorten it
127+
// 3. Adding to the mid x coordinate
128+
x: mid.x + (dxEnd * (rEnd - ARROW_LENGTH_REDUCER)) / rEnd,
129+
// Same calculation for y coordinate
130+
y: mid.y + (dyEnd * (rEnd - ARROW_LENGTH_REDUCER)) / rEnd,
131+
};
132+
133+
pathD = `M${from.x},${from.y} L${mid.x},${mid.y} L${end.x},${end.y}`;
134+
} else {
135+
// Calculate the new end point for the arrow
136+
// We subtract ARROW_LENGTH_REDUCER from the total distance to make the arrow
137+
// stop before reaching the center of the target square
138+
const end = {
139+
// Calculate new end x coordinate by:
140+
// 1. Taking the original x direction (dx)
141+
// 2. Scaling it by (r - ARROW_LENGTH_REDUCER) / r to shorten it
142+
// 3. Adding to the starting x coordinate
143+
x: from.x + (dx * (r - ARROW_LENGTH_REDUCER)) / r,
144+
// Same calculation for y coordinate
145+
y: from.y + (dy * (r - ARROW_LENGTH_REDUCER)) / r,
146+
};
147+
148+
pathD = `M${from.x},${from.y} L${end.x},${end.y}`;
149+
}
107150

108151
return (
109152
<Fragment
@@ -121,11 +164,9 @@ export function Arrows() {
121164
>
122165
<polygon points="0.3 0, 2 1.25, 0.3 2.5" fill={arrow.color} />
123166
</marker>
124-
<line
125-
x1={from.x}
126-
y1={from.y}
127-
x2={end.x}
128-
y2={end.y}
167+
<path
168+
d={pathD}
169+
fill="none"
129170
opacity={
130171
isArrowActive
131172
? arrowOptions.activeOpacity

0 commit comments

Comments
 (0)