Keep a transition's pace through new steps and pans (#309)
A wheel step in the middle of a transition restarted the ease-out curve at full speed, so a run of quick steps kicked at each one. A pan called finish() first and made the zoom jump to its target. Both made the zoom and the gliding lists feel jerky. - A new step starts from the speed the view already has and then eases out. Quick steps in one direction move in one stroke. A step the other way still starts from rest. - A pan takes the transition along. The zoom goes on while dragging and lands where it was heading, moved by the pan. This covers all eight pan places: scene and container, graph, plugin board, texture and pixel art, timeline, pattern, song and sound. - finish() is gone, it has no callers left. Dragging the scrollbar, a jump to a row, another document or a new view size still end the transition as before. Found: on a second step the old curve jumped to 2.47 times the speed the view had just before. Tests: - npm run check on stein2: 299 files, 4598 tests (5 new) - e2e 46 on stein2: ALL PASSED, 24 checks (1 new). A pan by 40/30 px during a 1000 ms zoom step leaves it moving (2.33 on the way from 2 to 3), it lands on 3 with the world point moved by the pan. - Counter-checks: with the pace reset to 3 the new unit test fails with 2.47 instead of at most 1.1. Without carry the pan test fails. - melektaus-atx went offline mid-run, so both ran on stein2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
be41b1f0d7
commit
597367c804
12 files changed
+307
-72
No files matched your search
@@ -593,8 +593,9 @@ export class GraphCanvas extends Widget {
|
||||
// The middle button pans from anywhere, a node under the pointer included – it is the one
|
||||
// gesture that never means "grab this". Nodes let it through for exactly that reason.
|
||||
const startPan = () => {
|
||||
this.tween.finish();
|
||||
this.panning = { startX: e.global.x, startY: e.global.y, panX: this.pan.x, panY: this.pan.y };
|
||||
this.tween.target(() => {
|
||||
this.panning = { startX: e.global.x, startY: e.global.y, panX: this.pan.x, panY: this.pan.y };
|
||||
});
|
||||
};
|
||||
if (e.button === 1) {
|
||||
startPan();
|
||||
@@ -782,9 +783,14 @@ export class GraphCanvas extends Widget {
|
||||
this.trackIncoming(dragged, e);
|
||||
return;
|
||||
}
|
||||
if (this.panning) {
|
||||
this.pan.x = this.panning.panX + (e.global.x - this.panning.startX);
|
||||
this.pan.y = this.panning.panY + (e.global.y - this.panning.startY);
|
||||
const { panning } = this;
|
||||
if (panning) {
|
||||
this.tween.carry(() => {
|
||||
this.pan = {
|
||||
x: panning.panX + (e.global.x - panning.startX),
|
||||
y: panning.panY + (e.global.y - panning.startY),
|
||||
};
|
||||
});
|
||||
this.applyView();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -76,13 +76,16 @@ export function panAndZoom(
|
||||
): void {
|
||||
let panning: { start: Point; pan: Point } | null = null;
|
||||
surface.on('pointerdown', (e: FederatedPointerEvent) => {
|
||||
tween.finish();
|
||||
panning = { start: { x: e.global.x, y: e.global.y }, pan: { ...get().pan } };
|
||||
tween.target(() => {
|
||||
panning = { start: { x: e.global.x, y: e.global.y }, pan: { ...get().pan } };
|
||||
});
|
||||
});
|
||||
surface.on('globalpointermove', (e: FederatedPointerEvent) => {
|
||||
if (!panning) return;
|
||||
const { start, pan } = panning;
|
||||
set({ ...get(), pan: { x: pan.x + e.global.x - start.x, y: pan.y + e.global.y - start.y } }, 'pan');
|
||||
tween.carry(() =>
|
||||
set({ ...get(), pan: { x: pan.x + e.global.x - start.x, y: pan.y + e.global.y - start.y } }, 'pan'),
|
||||
);
|
||||
});
|
||||
surface.on('pointerup', () => (panning = null));
|
||||
surface.on('pointerupoutside', () => (panning = null));
|
||||
|
||||
Reference in new issue
Block a user