Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(std): pan and pinch events were calculate relative to only one finger #8870

Merged
merged 3 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,9 @@ export class EdgelessRootBlockComponent extends BlockComponent<
const [p1, p2] = multiPointersState.pointers;

const dx =
(0.5 * (p1.delta.x + p2.delta.x)) / viewport.zoom / viewport.scale;
(0.25 * (p1.delta.x + p2.delta.x)) / viewport.zoom / viewport.scale;
const dy =
(0.5 * (p1.delta.y + p2.delta.y)) / viewport.zoom / viewport.scale;
(0.25 * (p1.delta.y + p2.delta.y)) / viewport.zoom / viewport.scale;
doodlewind marked this conversation as resolved.
Show resolved Hide resolved

// direction is opposite
viewport.applyDeltaCenter(-dx, -dy);
Expand Down
113 changes: 62 additions & 51 deletions packages/framework/block-std/src/event/control/pointer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IS_IPAD } from '@blocksuite/global/env';
import { Vec } from '@blocksuite/global/utils';

import type { UIEventDispatcher } from '../dispatcher.js';

Expand All @@ -9,7 +10,7 @@ import {
PointerEventState,
} from '../state/index.js';
import { EventScopeSourceType, EventSourceState } from '../state/source.js';
import { center, isFarEnough } from '../utils.js';
import { isFarEnough } from '../utils.js';

type PointerId = typeof PointerEvent.prototype.pointerId;

Expand Down Expand Up @@ -400,58 +401,41 @@ abstract class DualDragControllerBase extends PointerControllerBase {
return;
}

const { pointerId } = event;

const start1 =
this._startPointerStates.primary.raw.pointerId === pointerId
? this._startPointerStates.primary
: this._startPointerStates.secondary;

const last1 =
(this._lastPointerStates.primary?.raw.pointerId === pointerId
? this._lastPointerStates.primary
: this._lastPointerStates.secondary) ?? start1;

if (!isFarEnough(last1.raw, event)) return;

const state1 = new PointerEventState({
event,
rect: this._rect,
startX: start1.x,
startY: start1.y,
last: last1,
});
const { isPrimary } = event;
const startPrimaryState = this._startPointerStates.primary;
let lastPrimaryState = this._lastPointerStates.primary;

const start2 =
this._startPointerStates.primary.raw.pointerId !== pointerId
? this._startPointerStates.primary
: this._startPointerStates.secondary;
const startSecondaryState = this._startPointerStates.secondary;
let lastSecondaryState = this._lastPointerStates.secondary;

const last2 =
(this._lastPointerStates.primary?.raw.pointerId !== pointerId
? this._lastPointerStates.primary
: this._lastPointerStates.secondary) ?? start2;

const state2 = new PointerEventState({
event: last2.raw,
rect: this._rect,
startX: start2.x,
startY: start2.y,
last: last2,
});

if (!isFarEnough(state1.delta, state2.delta)) return;
if (isPrimary) {
lastPrimaryState = new PointerEventState({
event,
rect: this._rect,
startX: startPrimaryState.x,
startY: startPrimaryState.y,
last: lastPrimaryState,
});
} else {
lastSecondaryState = new PointerEventState({
event,
rect: this._rect,
startX: startSecondaryState.x,
startY: startSecondaryState.y,
last: lastSecondaryState,
});
}

const multiPointerState = new MultiPointerEventState(event, [
state1,
state2,
lastPrimaryState ?? startPrimaryState,
lastSecondaryState ?? startSecondaryState,
]);

this._handleMove(event, multiPointerState);

this._lastPointerStates = {
primary: state1.raw.isPrimary ? state1 : state2,
secondary: state1.raw.isPrimary ? state2 : state1,
primary: lastPrimaryState,
secondary: lastSecondaryState,
};
};

Expand Down Expand Up @@ -502,8 +486,30 @@ class PinchController extends DualDragControllerBase {
override _handleMove(event: PointerEvent, state: MultiPointerEventState) {
if (event.pointerType !== 'touch') return;

const deltaFirstPointer = state.pointers[0].delta;
const deltaSecondPointer = state.pointers[1].delta;

const deltaFirstPointerVec = Vec.toVec(deltaFirstPointer);
const deltaSecondPointerVec = Vec.toVec(deltaSecondPointer);

const deltaFirstPointerValue = Vec.len(deltaFirstPointerVec);
const deltaSecondPointerValue = Vec.len(deltaSecondPointerVec);

const deltaDotProduct = Vec.dpr(
deltaFirstPointerVec,
deltaSecondPointerVec
);

const deltaValueThreshold = 0.1;

// the changes of distance between two pointers is not far enough
if (!isFarEnough(state.pointers[0].delta, state.pointers[1].delta)) return;
if (
!isFarEnough(deltaFirstPointer, deltaSecondPointer) ||
deltaDotProduct > 0 ||
deltaFirstPointerValue < deltaValueThreshold ||
deltaSecondPointerValue < deltaValueThreshold
)
return;

this._dispatcher.run('pinch', createContext(event, state));
}
Expand All @@ -513,15 +519,20 @@ class PanController extends DualDragControllerBase {
override _handleMove(event: PointerEvent, state: MultiPointerEventState) {
if (event.pointerType !== 'touch') return;

// current center, last center = center move vector
// 0.5 * (a + da + b + db) - 0.5 * (a + b) = 0.5 * (da + db)
const centerMoveVec = center(
state.pointers[0].delta,
state.pointers[1].delta
const deltaFirstPointer = state.pointers[0].delta;
const deltaSecondPointer = state.pointers[1].delta;

const deltaDotProduct = Vec.dpr(
Vec.toVec(deltaFirstPointer),
Vec.toVec(deltaSecondPointer)
);

// the center move distance is not far enough
if (!isFarEnough({ x: 0, y: 0 }, centerMoveVec)) return;
if (
!isFarEnough(deltaFirstPointer, deltaSecondPointer) &&
deltaDotProduct < 0
)
return;

this._dispatcher.run('pan', createContext(event, state));
}
Expand Down
8 changes: 4 additions & 4 deletions tests/edgeless/basic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ test('zoom by pinch', async ({ page }) => {
{ x: CENTER_X + 100, y: CENTER_Y },
];
const to = [
{ x: CENTER_X - 50, y: CENTER_Y },
{ x: CENTER_X + 50, y: CENTER_Y },
{ x: CENTER_X - 50, y: CENTER_Y - 35 },
{ x: CENTER_X + 50, y: CENTER_Y + 35 },
];
await multiTouchDown(page, from);
await multiTouchMove(page, from, to);
Expand All @@ -166,8 +166,8 @@ test('zoom by pinch when edgeless is readonly', async ({ page }) => {
{ x: CENTER_X + 100, y: CENTER_Y },
];
const to = [
{ x: CENTER_X - 50, y: CENTER_Y },
{ x: CENTER_X + 50, y: CENTER_Y },
{ x: CENTER_X - 50, y: CENTER_Y - 35 },
{ x: CENTER_X + 50, y: CENTER_Y + 35 },
];
await multiTouchDown(page, from);
await multiTouchMove(page, from, to);
Expand Down
Loading