Browse Source

Don't reset cache while zooming using a gesture (#1103)

* Don't reset cache while zooming using a gesture

This reuses the cached canvas while the gesture is happening. Once it has stop updating, then recompute the cache with the proper zoom.

This should massively improve performance when panning on big scenes on mobile

Fixes #1056

* update snapshot tests
pull/1105/head
Christopher Chedeau 6 years ago committed by GitHub
parent
commit
24fa657093
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .watchmanconfig
  2. 1
      src/appState.ts
  3. 7
      src/components/App.tsx
  4. 18
      src/renderer/renderElement.ts
  5. 1
      src/scene/export.ts
  6. 1
      src/scene/types.ts
  7. 41
      src/tests/__snapshots__/regressionTests.test.tsx.snap
  8. 1
      src/types.ts

1
.watchmanconfig

@ -0,0 +1 @@ @@ -0,0 +1 @@
{}

1
src/appState.ts

@ -35,6 +35,7 @@ export function getDefaultAppState(): AppState { @@ -35,6 +35,7 @@ export function getDefaultAppState(): AppState {
lastPointerDownWith: "mouse",
selectedElementIds: {},
collaborators: new Map(),
shouldCacheIgnoreZoom: false,
};
}

7
src/components/App.tsx

@ -481,6 +481,7 @@ export class App extends React.Component<any, AppState> { @@ -481,6 +481,7 @@ export class App extends React.Component<any, AppState> {
viewBackgroundColor: this.state.viewBackgroundColor,
zoom: this.state.zoom,
remotePointerViewportCoords: pointerViewportCoords,
shouldCacheIgnoreZoom: this.state.shouldCacheIgnoreZoom,
},
{
renderOptimizations: true,
@ -1247,7 +1248,9 @@ export class App extends React.Component<any, AppState> { @@ -1247,7 +1248,9 @@ export class App extends React.Component<any, AppState> {
scrollX: normalizeScroll(this.state.scrollX + deltaX / this.state.zoom),
scrollY: normalizeScroll(this.state.scrollY + deltaY / this.state.zoom),
zoom: getNormalizedZoom(gesture.initialScale! * scaleFactor),
shouldCacheIgnoreZoom: true,
});
this.resetShouldCacheIgnoreZoomDebounced();
} else {
gesture.lastCenter = gesture.initialDistance = gesture.initialScale = null;
}
@ -2553,6 +2556,10 @@ export class App extends React.Component<any, AppState> { @@ -2553,6 +2556,10 @@ export class App extends React.Component<any, AppState> {
this.socket && this.broadcastMouseLocation({ pointerCoords });
};
private resetShouldCacheIgnoreZoomDebounced = debounce(() => {
this.setState({ shouldCacheIgnoreZoom: false });
}, 1000);
private saveDebounced = debounce(() => {
saveToLocalStorage(globalSceneState.getAllElements(), this.state);
}, 300);

18
src/renderer/renderElement.ts

@ -245,7 +245,11 @@ function generateElement( @@ -245,7 +245,11 @@ function generateElement(
}
const zoom = sceneState ? sceneState.zoom : 1;
const prevElementWithCanvas = elementWithCanvasCache.get(element);
if (!prevElementWithCanvas || prevElementWithCanvas.canvasZoom !== zoom) {
const shouldRegenerateBecauseZoom =
prevElementWithCanvas &&
prevElementWithCanvas.canvasZoom !== zoom &&
!sceneState?.shouldCacheIgnoreZoom;
if (!prevElementWithCanvas || shouldRegenerateBecauseZoom) {
const elementWithCanvas = generateElementCanvas(element, zoom);
elementWithCanvasCache.set(element, elementWithCanvas);
return elementWithCanvas;
@ -261,8 +265,8 @@ function drawElementFromCanvas( @@ -261,8 +265,8 @@ function drawElementFromCanvas(
) {
context.scale(1 / window.devicePixelRatio, 1 / window.devicePixelRatio);
context.translate(
-CANVAS_PADDING / sceneState.zoom,
-CANVAS_PADDING / sceneState.zoom,
-CANVAS_PADDING / elementWithCanvas.canvasZoom,
-CANVAS_PADDING / elementWithCanvas.canvasZoom,
);
context.drawImage(
elementWithCanvas.canvas!,
@ -276,12 +280,12 @@ function drawElementFromCanvas( @@ -276,12 +280,12 @@ function drawElementFromCanvas(
(Math.floor(elementWithCanvas.element.y) + sceneState.scrollY) *
window.devicePixelRatio,
),
elementWithCanvas.canvas!.width / sceneState.zoom,
elementWithCanvas.canvas!.height / sceneState.zoom,
elementWithCanvas.canvas!.width / elementWithCanvas.canvasZoom,
elementWithCanvas.canvas!.height / elementWithCanvas.canvasZoom,
);
context.translate(
CANVAS_PADDING / sceneState.zoom,
CANVAS_PADDING / sceneState.zoom,
CANVAS_PADDING / elementWithCanvas.canvasZoom,
CANVAS_PADDING / elementWithCanvas.canvasZoom,
);
context.scale(window.devicePixelRatio, window.devicePixelRatio);
}

1
src/scene/export.ts

@ -50,6 +50,7 @@ export function exportToCanvas( @@ -50,6 +50,7 @@ export function exportToCanvas(
scrollY: normalizeScroll(-minY + exportPadding),
zoom: 1,
remotePointerViewportCoords: {},
shouldCacheIgnoreZoom: false,
},
{
renderScrollbars: false,

1
src/scene/types.ts

@ -7,6 +7,7 @@ export type SceneState = { @@ -7,6 +7,7 @@ export type SceneState = {
// null indicates transparent bg
viewBackgroundColor: string | null;
zoom: number;
shouldCacheIgnoreZoom: boolean;
remotePointerViewportCoords: { [id: string]: { x: number; y: number } };
};

41
src/tests/__snapshots__/regressionTests.test.tsx.snap

@ -33,6 +33,7 @@ Object { @@ -33,6 +33,7 @@ Object {
"id2": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -211,6 +212,7 @@ Object { @@ -211,6 +212,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -316,6 +318,7 @@ Object { @@ -316,6 +318,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -558,6 +561,7 @@ Object { @@ -558,6 +561,7 @@ Object {
"id1": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -699,6 +703,7 @@ Object { @@ -699,6 +703,7 @@ Object {
"id2": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -873,6 +878,7 @@ Object { @@ -873,6 +878,7 @@ Object {
"id2": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -1053,6 +1059,7 @@ Object { @@ -1053,6 +1059,7 @@ Object {
"id3": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -1320,6 +1327,7 @@ Object { @@ -1320,6 +1327,7 @@ Object {
"scrolledOutside": false,
"selectedElementIds": Object {},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -1895,6 +1903,7 @@ Object { @@ -1895,6 +1903,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2000,6 +2009,7 @@ Object { @@ -2000,6 +2009,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2105,6 +2115,7 @@ Object { @@ -2105,6 +2115,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2210,6 +2221,7 @@ Object { @@ -2210,6 +2221,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2337,6 +2349,7 @@ Object { @@ -2337,6 +2349,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2464,6 +2477,7 @@ Object { @@ -2464,6 +2477,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2591,6 +2605,7 @@ Object { @@ -2591,6 +2605,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2696,6 +2711,7 @@ Object { @@ -2696,6 +2711,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2801,6 +2817,7 @@ Object { @@ -2801,6 +2817,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -2928,6 +2945,7 @@ Object { @@ -2928,6 +2945,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -3033,6 +3051,7 @@ Object { @@ -3033,6 +3051,7 @@ Object {
"id0": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": true,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -3098,6 +3117,7 @@ Object { @@ -3098,6 +3117,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -3754,6 +3774,7 @@ Object { @@ -3754,6 +3774,7 @@ Object {
"id7": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -4102,6 +4123,7 @@ Object { @@ -4102,6 +4123,7 @@ Object {
"id5": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -4380,6 +4402,7 @@ Object { @@ -4380,6 +4402,7 @@ Object {
"id3": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -4588,6 +4611,7 @@ Object { @@ -4588,6 +4611,7 @@ Object {
"id1": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -4742,6 +4766,7 @@ Object { @@ -4742,6 +4766,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -5370,6 +5395,7 @@ Object { @@ -5370,6 +5395,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -5928,6 +5954,7 @@ Object { @@ -5928,6 +5954,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -6416,6 +6443,7 @@ Object { @@ -6416,6 +6443,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -6835,6 +6863,7 @@ Object { @@ -6835,6 +6863,7 @@ Object {
"id8": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -7218,6 +7247,7 @@ Object { @@ -7218,6 +7247,7 @@ Object {
"id6": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -7531,6 +7561,7 @@ Object { @@ -7531,6 +7561,7 @@ Object {
"id4": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -7774,6 +7805,7 @@ Object { @@ -7774,6 +7805,7 @@ Object {
"id2": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -7963,6 +7995,7 @@ Object { @@ -7963,6 +7995,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -8626,6 +8659,7 @@ Object { @@ -8626,6 +8659,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -9219,6 +9253,7 @@ Object { @@ -9219,6 +9253,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -9742,6 +9777,7 @@ Object { @@ -9742,6 +9777,7 @@ Object {
"id9": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -10191,6 +10227,7 @@ Object { @@ -10191,6 +10227,7 @@ Object {
"id4": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -10419,6 +10456,7 @@ Object { @@ -10419,6 +10456,7 @@ Object {
"scrolledOutside": false,
"selectedElementIds": Object {},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -10468,6 +10506,7 @@ Object { @@ -10468,6 +10506,7 @@ Object {
"id1": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": true,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -10517,6 +10556,7 @@ Object { @@ -10517,6 +10556,7 @@ Object {
"id2": true,
},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}
@ -10785,6 +10825,7 @@ Object { @@ -10785,6 +10825,7 @@ Object {
"scrolledOutside": false,
"selectedElementIds": Object {},
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"viewBackgroundColor": "#ffffff",
"zoom": 1,
}

1
src/types.ts

@ -42,6 +42,7 @@ export type AppState = { @@ -42,6 +42,7 @@ export type AppState = {
lastPointerDownWith: PointerType;
selectedElementIds: { [id: string]: boolean };
collaborators: Map<string, { pointer?: { x: number; y: number } }>;
shouldCacheIgnoreZoom: boolean;
};
export type PointerCoords = Readonly<{

Loading…
Cancel
Save