Commit 6846df5
authored
fix(arrows): clamp boundary anchors to avoid degenerate intersections (tldraw#8130)
Closes tldraw#8125
https://github.com/user-attachments/assets/cf96fc2a-c7f2-4448-8ccf-42e0eaa5ba2b
Arrow endpoints flicker when `normalizedAnchor` coordinates are exactly
0 or 1 (shape edges/corners). At these exact values, the intersection
math becomes numerically unstable — small floating-point errors cause
intersections to toggle between found and not-found across frames.
**Solution:** if arrow is precise or forceImprecise, clamp each anchor
coordinate from [0, 1] to [0.001, 0.999]. This clamping happens inside
`getArrowTerminalInArrowSpace`, which runs every time the arrow info is
recomputed (i.e. whenever the arrow or its bound shapes change). The
binding record in the store is never modified — the nudge only exists
ephemerally during computation, so the intersection math never sees an
exact boundary value.
### Change type
- [x] `bugfix`
### Test plan
1. Create a shape and programmatically bind a self-referential arrow
with anchors at exact boundary positions (e.g. `{x: 0, y: 0}`, `{x: 0.5,
y: 0}`)
2. Verify arrows render without flickering
3. Resize and move the shape — arrows should remain stable
- [x] Unit tests
### Release notes
- Fix arrow endpoint flickering when anchors are at exact shape
boundaries
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches core arrow terminal computation; clamping precise anchors near
0/1 can subtly shift endpoints (up to ~0.1% of shape size) and may
affect arrow rendering/attachment in edge cases.
>
> **Overview**
> Prevents arrow endpoint flicker when a bound terminal’s
`normalizedAnchor` lands exactly on a shape edge/corner by clamping
precise anchors away from `0`/`1` during `getArrowTerminalInArrowSpace`
computations.
>
> Adds a small epsilon-based `clampNormalizedAnchor` helper and
refactors the terminal point calculation to use the clamped anchor
without mutating stored binding data.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f4ecde2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 0d748e7 commit 6846df5
1 file changed
Lines changed: 15 additions & 10 deletions
File tree
- packages/tldraw/src/lib/shapes/arrow
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
18 | 26 | | |
19 | 27 | | |
20 | 28 | | |
| |||
78 | 86 | | |
79 | 87 | | |
80 | 88 | | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
91 | 96 | | |
92 | 97 | | |
93 | 98 | | |
| |||
0 commit comments