* Continuous easing auto-fit — refreshes the follower's target from live * positions while the user has not taken manual control of the camera. The * ticker eases the viewport toward this target each frame, so bursty * producers like the d3-force worker streaming positions every ~66 ms driv
(_duration = 200)
| 2295 | * rate, so the value is intentionally ignored. |
| 2296 | */ |
| 2297 | scheduleAutoFit(_duration = 200): void { |
| 2298 | if (this.hasUserMovedCamera) return; |
| 2299 | if (this.autoFitSuspended) return; |
| 2300 | if (this.nodes.size === 0) return; |
| 2301 | // A manual zoomToFit/zoomToNodes animation is in progress — the |
| 2302 | // user (or another explicit caller) has the most-recent intent. |
| 2303 | // Don't overwrite their target with auto-fit. |
| 2304 | if (this.cancelAnimation !== null) return; |
| 2305 | // Refresh the follower's target from live positions. Cheap (O(n) |
| 2306 | // bounds compute), called at worker tick rate (~66 ms). The |
| 2307 | // ticker eases `vp` toward this target each frame; if the |
| 2308 | // layout keeps moving, the target keeps shifting and the camera |
| 2309 | // smoothly chases it — no discrete animations, no zoom thrash |
| 2310 | // (Fix #9 / Option C). |
| 2311 | const target = this.computeFitTarget(); |
| 2312 | if (target) this.autoFitTarget = target; |
| 2313 | } |
| 2314 | |
| 2315 | private computeFitTarget(): Viewport | null { |
| 2316 | if (this.nodes.size === 0) return null; |
no test coverage detected