mock: キーを画面の端へ寄せると、キャンバスを自動でスクロールする(T-30 単位4)

ノードのドラッグ中にポインタがSVGの端から32px以内か外にあると、
requestAnimationFrame で pan を動かし続け、DOM更新後の最後のポインタ位置で
ドラッグ位置を計算し直す。速度は端に近いほど速く、上限480px/秒(autoPanVelocity)。
範囲選択とパンのドラッグは対象外。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NznQtmVPoQAnietqwr1auL
This commit is contained in:
2026-10-22 09:39:19 +09:00
co-authored by Claude Opus 5.5
parent 38954e9b36
commit e50722948d
4 changed files with 133 additions and 16 deletions
+9 -1
View File
@@ -17,7 +17,7 @@ import {
treeIndex,
visibleNodeIds,
} from "../src/ui/phy/logic";
import { fitViewport, zoomAround } from "../src/ui/phy/viewport";
import { autoPanVelocity, fitViewport, zoomAround } from "../src/ui/phy/viewport";
import type { PhyFile, Node as PhyNode } from "../src/domain/phy";
const phy: PhyFile = {
version: "0.1.0",
@@ -189,4 +189,12 @@ describe("PHY pure interaction rules", () => {
expect((cursor.x - zoomed.pan.x) / zoomed.zoom).toBeCloseTo(world.x);
expect((cursor.y - zoomed.pan.y) / zoomed.zoom).toBeCloseTo(world.y);
});
it("scales auto-pan speed near edges, outside the canvas, and at corners", () => {
const bounds = { x: 10, y: 20, width: 200, height: 100 };
expect(autoPanVelocity({ x: 110, y: 70 }, bounds)).toEqual({ x: 0, y: 0 });
expect(autoPanVelocity({ x: 194, y: 70 }, bounds)).toEqual({ x: 240, y: 0 });
expect(autoPanVelocity({ x: 210, y: 70 }, bounds)).toEqual({ x: 480, y: 0 });
expect(autoPanVelocity({ x: 220, y: 70 }, bounds)).toEqual({ x: 480, y: 0 });
expect(autoPanVelocity({ x: 210, y: 10 }, bounds)).toEqual({ x: 480, y: -480 });
});
});