Make gesture.pointers a Map instead of an array of pointers (#877)

This commit is contained in:
Pete Hunt 2020-03-08 19:25:16 -07:00 committed by GitHub
parent 92ba401da8
commit 8d8f9f23bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 30 deletions

View File

@ -118,7 +118,7 @@ let currentScrollBars: ScrollBars = { horizontal: null, vertical: null };
let lastPointerUp: ((event: any) => void) | null = null; let lastPointerUp: ((event: any) => void) | null = null;
const gesture: Gesture = { const gesture: Gesture = {
pointers: [], pointers: new Map(),
lastCenter: null, lastCenter: null,
initialDistance: null, initialDistance: null,
initialScale: null, initialScale: null,
@ -354,7 +354,7 @@ export class App extends React.Component<any, AppState> {
this.state.draggingElement === null this.state.draggingElement === null
) { ) {
this.selectShapeTool(shape); this.selectShapeTool(shape);
} else if (event.key === KEYS.SPACE && gesture.pointers.length === 0) { } else if (event.key === KEYS.SPACE && gesture.pointers.size === 0) {
isHoldingSpace = true; isHoldingSpace = true;
document.documentElement.style.cursor = CURSOR_TYPE.GRABBING; document.documentElement.style.cursor = CURSOR_TYPE.GRABBING;
} }
@ -465,9 +465,7 @@ export class App extends React.Component<any, AppState> {
}; };
removePointer = (event: React.PointerEvent<HTMLElement>) => { removePointer = (event: React.PointerEvent<HTMLElement>) => {
gesture.pointers = gesture.pointers.filter( gesture.pointers.delete(event.pointerId);
pointer => pointer.id !== event.pointerId,
);
}; };
public render() { public render() {
@ -722,23 +720,18 @@ export class App extends React.Component<any, AppState> {
private handleCanvasPointerMove = ( private handleCanvasPointerMove = (
event: React.PointerEvent<HTMLCanvasElement>, event: React.PointerEvent<HTMLCanvasElement>,
) => { ) => {
gesture.pointers = gesture.pointers.map(pointer => gesture.pointers.set(event.pointerId, {
pointer.id === event.pointerId
? {
id: event.pointerId,
x: event.clientX, x: event.clientX,
y: event.clientY, y: event.clientY,
} });
: pointer,
);
if (gesture.pointers.length === 2) { if (gesture.pointers.size === 2) {
const center = getCenter(gesture.pointers); const center = getCenter(gesture.pointers);
const deltaX = center.x - gesture.lastCenter!.x; const deltaX = center.x - gesture.lastCenter!.x;
const deltaY = center.y - gesture.lastCenter!.y; const deltaY = center.y - gesture.lastCenter!.y;
gesture.lastCenter = center; gesture.lastCenter = center;
const distance = getDistance(gesture.pointers); const distance = getDistance(Array.from(gesture.pointers.values()));
const scaleFactor = distance / gesture.initialDistance!; const scaleFactor = distance / gesture.initialDistance!;
this.setState({ this.setState({
@ -835,7 +828,7 @@ export class App extends React.Component<any, AppState> {
// pan canvas on wheel button drag or space+drag // pan canvas on wheel button drag or space+drag
if ( if (
gesture.pointers.length === 0 && gesture.pointers.size === 0 &&
(event.button === POINTER_BUTTON.WHEEL || (event.button === POINTER_BUTTON.WHEEL ||
(event.button === POINTER_BUTTON.MAIN && isHoldingSpace)) (event.button === POINTER_BUTTON.MAIN && isHoldingSpace))
) { ) {
@ -883,15 +876,17 @@ export class App extends React.Component<any, AppState> {
return; return;
} }
gesture.pointers.push({ gesture.pointers.set(event.pointerId, {
id: event.pointerId,
x: event.clientX, x: event.clientX,
y: event.clientY, y: event.clientY,
}); });
if (gesture.pointers.length === 2) {
if (gesture.pointers.size === 2) {
gesture.lastCenter = getCenter(gesture.pointers); gesture.lastCenter = getCenter(gesture.pointers);
gesture.initialScale = this.state.zoom; gesture.initialScale = this.state.zoom;
gesture.initialDistance = getDistance(gesture.pointers); gesture.initialDistance = getDistance(
Array.from(gesture.pointers.values()),
);
} }
// fixes pointermove causing selection of UI texts #32 // fixes pointermove causing selection of UI texts #32
@ -904,7 +899,7 @@ export class App extends React.Component<any, AppState> {
} }
// don't select while panning // don't select while panning
if (gesture.pointers.length > 1) { if (gesture.pointers.size > 1) {
return; return;
} }

View File

@ -1,14 +1,15 @@
import { Pointer } from "./types"; import { PointerCoords } from "./types";
import { normalizeScroll } from "./scene"; import { normalizeScroll } from "./scene";
export function getCenter(pointers: readonly Pointer[]) { export function getCenter(pointers: Map<number, PointerCoords>) {
const allCoords = Array.from(pointers.values());
return { return {
x: normalizeScroll(sum(pointers, pointer => pointer.x) / pointers.length), x: normalizeScroll(sum(allCoords, coords => coords.x) / allCoords.length),
y: normalizeScroll(sum(pointers, pointer => pointer.y) / pointers.length), y: normalizeScroll(sum(allCoords, coords => coords.y) / allCoords.length),
}; };
} }
export function getDistance([a, b]: readonly Pointer[]) { export function getDistance([a, b]: readonly PointerCoords[]) {
return Math.hypot(a.x - b.x, a.y - b.y); return Math.hypot(a.x - b.x, a.y - b.y);
} }

View File

@ -36,14 +36,13 @@ export type AppState = {
selectedElementIds: { [id: string]: boolean }; selectedElementIds: { [id: string]: boolean };
}; };
export type Pointer = Readonly<{ export type PointerCoords = Readonly<{
id: number;
x: number; x: number;
y: number; y: number;
}>; }>;
export type Gesture = { export type Gesture = {
pointers: Array<Pointer>; pointers: Map<number, PointerCoords>;
lastCenter: { x: number; y: number } | null; lastCenter: { x: number; y: number } | null;
initialDistance: number | null; initialDistance: number | null;
initialScale: number | null; initialScale: number | null;