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
vanilla_orig
Christopher Chedeau 4 years ago
parent
commit
24fa657093
No account linked to committer's email address

+ 1
- 0
.watchmanconfig View File

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

+ 1
- 0
src/appState.ts View File

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

+ 7
- 0
src/components/App.tsx View File

@@ -481,6 +481,7 @@ export class App extends React.Component<any, AppState> {
481 481
         viewBackgroundColor: this.state.viewBackgroundColor,
482 482
         zoom: this.state.zoom,
483 483
         remotePointerViewportCoords: pointerViewportCoords,
484
+        shouldCacheIgnoreZoom: this.state.shouldCacheIgnoreZoom,
484 485
       },
485 486
       {
486 487
         renderOptimizations: true,
@@ -1247,7 +1248,9 @@ export class App extends React.Component<any, AppState> {
1247 1248
         scrollX: normalizeScroll(this.state.scrollX + deltaX / this.state.zoom),
1248 1249
         scrollY: normalizeScroll(this.state.scrollY + deltaY / this.state.zoom),
1249 1250
         zoom: getNormalizedZoom(gesture.initialScale! * scaleFactor),
1251
+        shouldCacheIgnoreZoom: true,
1250 1252
       });
1253
+      this.resetShouldCacheIgnoreZoomDebounced();
1251 1254
     } else {
1252 1255
       gesture.lastCenter = gesture.initialDistance = gesture.initialScale = null;
1253 1256
     }
@@ -2553,6 +2556,10 @@ export class App extends React.Component<any, AppState> {
2553 2556
     this.socket && this.broadcastMouseLocation({ pointerCoords });
2554 2557
   };
2555 2558
 
2559
+  private resetShouldCacheIgnoreZoomDebounced = debounce(() => {
2560
+    this.setState({ shouldCacheIgnoreZoom: false });
2561
+  }, 1000);
2562
+
2556 2563
   private saveDebounced = debounce(() => {
2557 2564
     saveToLocalStorage(globalSceneState.getAllElements(), this.state);
2558 2565
   }, 300);

+ 11
- 7
src/renderer/renderElement.ts View File

@@ -245,7 +245,11 @@ function generateElement(
245 245
   }
246 246
   const zoom = sceneState ? sceneState.zoom : 1;
247 247
   const prevElementWithCanvas = elementWithCanvasCache.get(element);
248
-  if (!prevElementWithCanvas || prevElementWithCanvas.canvasZoom !== zoom) {
248
+  const shouldRegenerateBecauseZoom =
249
+    prevElementWithCanvas &&
250
+    prevElementWithCanvas.canvasZoom !== zoom &&
251
+    !sceneState?.shouldCacheIgnoreZoom;
252
+  if (!prevElementWithCanvas || shouldRegenerateBecauseZoom) {
249 253
     const elementWithCanvas = generateElementCanvas(element, zoom);
250 254
     elementWithCanvasCache.set(element, elementWithCanvas);
251 255
     return elementWithCanvas;
@@ -261,8 +265,8 @@ function drawElementFromCanvas(
261 265
 ) {
262 266
   context.scale(1 / window.devicePixelRatio, 1 / window.devicePixelRatio);
263 267
   context.translate(
264
-    -CANVAS_PADDING / sceneState.zoom,
265
-    -CANVAS_PADDING / sceneState.zoom,
268
+    -CANVAS_PADDING / elementWithCanvas.canvasZoom,
269
+    -CANVAS_PADDING / elementWithCanvas.canvasZoom,
266 270
   );
267 271
   context.drawImage(
268 272
     elementWithCanvas.canvas!,
@@ -276,12 +280,12 @@ function drawElementFromCanvas(
276 280
         (Math.floor(elementWithCanvas.element.y) + sceneState.scrollY) *
277 281
           window.devicePixelRatio,
278 282
     ),
279
-    elementWithCanvas.canvas!.width / sceneState.zoom,
280
-    elementWithCanvas.canvas!.height / sceneState.zoom,
283
+    elementWithCanvas.canvas!.width / elementWithCanvas.canvasZoom,
284
+    elementWithCanvas.canvas!.height / elementWithCanvas.canvasZoom,
281 285
   );
282 286
   context.translate(
283
-    CANVAS_PADDING / sceneState.zoom,
284
-    CANVAS_PADDING / sceneState.zoom,
287
+    CANVAS_PADDING / elementWithCanvas.canvasZoom,
288
+    CANVAS_PADDING / elementWithCanvas.canvasZoom,
285 289
   );
286 290
   context.scale(window.devicePixelRatio, window.devicePixelRatio);
287 291
 }

+ 1
- 0
src/scene/export.ts View File

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

+ 1
- 0
src/scene/types.ts View File

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

+ 41
- 0
src/tests/__snapshots__/regressionTests.test.tsx.snap View File

@@ -33,6 +33,7 @@ Object {
33 33
     "id2": true,
34 34
   },
35 35
   "selectionElement": null,
36
+  "shouldCacheIgnoreZoom": false,
36 37
   "viewBackgroundColor": "#ffffff",
37 38
   "zoom": 1,
38 39
 }
@@ -211,6 +212,7 @@ Object {
211 212
     "id0": true,
212 213
   },
213 214
   "selectionElement": null,
215
+  "shouldCacheIgnoreZoom": false,
214 216
   "viewBackgroundColor": "#ffffff",
215 217
   "zoom": 1,
216 218
 }
@@ -316,6 +318,7 @@ Object {
316 318
     "id0": true,
317 319
   },
318 320
   "selectionElement": null,
321
+  "shouldCacheIgnoreZoom": false,
319 322
   "viewBackgroundColor": "#ffffff",
320 323
   "zoom": 1,
321 324
 }
@@ -558,6 +561,7 @@ Object {
558 561
     "id1": true,
559 562
   },
560 563
   "selectionElement": null,
564
+  "shouldCacheIgnoreZoom": false,
561 565
   "viewBackgroundColor": "#ffffff",
562 566
   "zoom": 1,
563 567
 }
@@ -699,6 +703,7 @@ Object {
699 703
     "id2": true,
700 704
   },
701 705
   "selectionElement": null,
706
+  "shouldCacheIgnoreZoom": false,
702 707
   "viewBackgroundColor": "#ffffff",
703 708
   "zoom": 1,
704 709
 }
@@ -873,6 +878,7 @@ Object {
873 878
     "id2": true,
874 879
   },
875 880
   "selectionElement": null,
881
+  "shouldCacheIgnoreZoom": false,
876 882
   "viewBackgroundColor": "#ffffff",
877 883
   "zoom": 1,
878 884
 }
@@ -1053,6 +1059,7 @@ Object {
1053 1059
     "id3": true,
1054 1060
   },
1055 1061
   "selectionElement": null,
1062
+  "shouldCacheIgnoreZoom": false,
1056 1063
   "viewBackgroundColor": "#ffffff",
1057 1064
   "zoom": 1,
1058 1065
 }
@@ -1320,6 +1327,7 @@ Object {
1320 1327
   "scrolledOutside": false,
1321 1328
   "selectedElementIds": Object {},
1322 1329
   "selectionElement": null,
1330
+  "shouldCacheIgnoreZoom": false,
1323 1331
   "viewBackgroundColor": "#ffffff",
1324 1332
   "zoom": 1,
1325 1333
 }
@@ -1895,6 +1903,7 @@ Object {
1895 1903
     "id0": true,
1896 1904
   },
1897 1905
   "selectionElement": null,
1906
+  "shouldCacheIgnoreZoom": false,
1898 1907
   "viewBackgroundColor": "#ffffff",
1899 1908
   "zoom": 1,
1900 1909
 }
@@ -2000,6 +2009,7 @@ Object {
2000 2009
     "id0": true,
2001 2010
   },
2002 2011
   "selectionElement": null,
2012
+  "shouldCacheIgnoreZoom": false,
2003 2013
   "viewBackgroundColor": "#ffffff",
2004 2014
   "zoom": 1,
2005 2015
 }
@@ -2105,6 +2115,7 @@ Object {
2105 2115
     "id0": true,
2106 2116
   },
2107 2117
   "selectionElement": null,
2118
+  "shouldCacheIgnoreZoom": false,
2108 2119
   "viewBackgroundColor": "#ffffff",
2109 2120
   "zoom": 1,
2110 2121
 }
@@ -2210,6 +2221,7 @@ Object {
2210 2221
     "id0": true,
2211 2222
   },
2212 2223
   "selectionElement": null,
2224
+  "shouldCacheIgnoreZoom": false,
2213 2225
   "viewBackgroundColor": "#ffffff",
2214 2226
   "zoom": 1,
2215 2227
 }
@@ -2337,6 +2349,7 @@ Object {
2337 2349
     "id0": true,
2338 2350
   },
2339 2351
   "selectionElement": null,
2352
+  "shouldCacheIgnoreZoom": false,
2340 2353
   "viewBackgroundColor": "#ffffff",
2341 2354
   "zoom": 1,
2342 2355
 }
@@ -2464,6 +2477,7 @@ Object {
2464 2477
     "id0": true,
2465 2478
   },
2466 2479
   "selectionElement": null,
2480
+  "shouldCacheIgnoreZoom": false,
2467 2481
   "viewBackgroundColor": "#ffffff",
2468 2482
   "zoom": 1,
2469 2483
 }
@@ -2591,6 +2605,7 @@ Object {
2591 2605
     "id0": true,
2592 2606
   },
2593 2607
   "selectionElement": null,
2608
+  "shouldCacheIgnoreZoom": false,
2594 2609
   "viewBackgroundColor": "#ffffff",
2595 2610
   "zoom": 1,
2596 2611
 }
@@ -2696,6 +2711,7 @@ Object {
2696 2711
     "id0": true,
2697 2712
   },
2698 2713
   "selectionElement": null,
2714
+  "shouldCacheIgnoreZoom": false,
2699 2715
   "viewBackgroundColor": "#ffffff",
2700 2716
   "zoom": 1,
2701 2717
 }
@@ -2801,6 +2817,7 @@ Object {
2801 2817
     "id0": true,
2802 2818
   },
2803 2819
   "selectionElement": null,
2820
+  "shouldCacheIgnoreZoom": false,
2804 2821
   "viewBackgroundColor": "#ffffff",
2805 2822
   "zoom": 1,
2806 2823
 }
@@ -2928,6 +2945,7 @@ Object {
2928 2945
     "id0": true,
2929 2946
   },
2930 2947
   "selectionElement": null,
2948
+  "shouldCacheIgnoreZoom": false,
2931 2949
   "viewBackgroundColor": "#ffffff",
2932 2950
   "zoom": 1,
2933 2951
 }
@@ -3033,6 +3051,7 @@ Object {
3033 3051
     "id0": true,
3034 3052
   },
3035 3053
   "selectionElement": null,
3054
+  "shouldCacheIgnoreZoom": true,
3036 3055
   "viewBackgroundColor": "#ffffff",
3037 3056
   "zoom": 1,
3038 3057
 }
@@ -3098,6 +3117,7 @@ Object {
3098 3117
     "id9": true,
3099 3118
   },
3100 3119
   "selectionElement": null,
3120
+  "shouldCacheIgnoreZoom": false,
3101 3121
   "viewBackgroundColor": "#ffffff",
3102 3122
   "zoom": 1,
3103 3123
 }
@@ -3754,6 +3774,7 @@ Object {
3754 3774
     "id7": true,
3755 3775
   },
3756 3776
   "selectionElement": null,
3777
+  "shouldCacheIgnoreZoom": false,
3757 3778
   "viewBackgroundColor": "#ffffff",
3758 3779
   "zoom": 1,
3759 3780
 }
@@ -4102,6 +4123,7 @@ Object {
4102 4123
     "id5": true,
4103 4124
   },
4104 4125
   "selectionElement": null,
4126
+  "shouldCacheIgnoreZoom": false,
4105 4127
   "viewBackgroundColor": "#ffffff",
4106 4128
   "zoom": 1,
4107 4129
 }
@@ -4380,6 +4402,7 @@ Object {
4380 4402
     "id3": true,
4381 4403
   },
4382 4404
   "selectionElement": null,
4405
+  "shouldCacheIgnoreZoom": false,
4383 4406
   "viewBackgroundColor": "#ffffff",
4384 4407
   "zoom": 1,
4385 4408
 }
@@ -4588,6 +4611,7 @@ Object {
4588 4611
     "id1": true,
4589 4612
   },
4590 4613
   "selectionElement": null,
4614
+  "shouldCacheIgnoreZoom": false,
4591 4615
   "viewBackgroundColor": "#ffffff",
4592 4616
   "zoom": 1,
4593 4617
 }
@@ -4742,6 +4766,7 @@ Object {
4742 4766
     "id9": true,
4743 4767
   },
4744 4768
   "selectionElement": null,
4769
+  "shouldCacheIgnoreZoom": false,
4745 4770
   "viewBackgroundColor": "#ffffff",
4746 4771
   "zoom": 1,
4747 4772
 }
@@ -5370,6 +5395,7 @@ Object {
5370 5395
     "id9": true,
5371 5396
   },
5372 5397
   "selectionElement": null,
5398
+  "shouldCacheIgnoreZoom": false,
5373 5399
   "viewBackgroundColor": "#ffffff",
5374 5400
   "zoom": 1,
5375 5401
 }
@@ -5928,6 +5954,7 @@ Object {
5928 5954
     "id9": true,
5929 5955
   },
5930 5956
   "selectionElement": null,
5957
+  "shouldCacheIgnoreZoom": false,
5931 5958
   "viewBackgroundColor": "#ffffff",
5932 5959
   "zoom": 1,
5933 5960
 }
@@ -6416,6 +6443,7 @@ Object {
6416 6443
     "id9": true,
6417 6444
   },
6418 6445
   "selectionElement": null,
6446
+  "shouldCacheIgnoreZoom": false,
6419 6447
   "viewBackgroundColor": "#ffffff",
6420 6448
   "zoom": 1,
6421 6449
 }
@@ -6835,6 +6863,7 @@ Object {
6835 6863
     "id8": true,
6836 6864
   },
6837 6865
   "selectionElement": null,
6866
+  "shouldCacheIgnoreZoom": false,
6838 6867
   "viewBackgroundColor": "#ffffff",
6839 6868
   "zoom": 1,
6840 6869
 }
@@ -7218,6 +7247,7 @@ Object {
7218 7247
     "id6": true,
7219 7248
   },
7220 7249
   "selectionElement": null,
7250
+  "shouldCacheIgnoreZoom": false,
7221 7251
   "viewBackgroundColor": "#ffffff",
7222 7252
   "zoom": 1,
7223 7253
 }
@@ -7531,6 +7561,7 @@ Object {
7531 7561
     "id4": true,
7532 7562
   },
7533 7563
   "selectionElement": null,
7564
+  "shouldCacheIgnoreZoom": false,
7534 7565
   "viewBackgroundColor": "#ffffff",
7535 7566
   "zoom": 1,
7536 7567
 }
@@ -7774,6 +7805,7 @@ Object {
7774 7805
     "id2": true,
7775 7806
   },
7776 7807
   "selectionElement": null,
7808
+  "shouldCacheIgnoreZoom": false,
7777 7809
   "viewBackgroundColor": "#ffffff",
7778 7810
   "zoom": 1,
7779 7811
 }
@@ -7963,6 +7995,7 @@ Object {
7963 7995
     "id9": true,
7964 7996
   },
7965 7997
   "selectionElement": null,
7998
+  "shouldCacheIgnoreZoom": false,
7966 7999
   "viewBackgroundColor": "#ffffff",
7967 8000
   "zoom": 1,
7968 8001
 }
@@ -8626,6 +8659,7 @@ Object {
8626 8659
     "id9": true,
8627 8660
   },
8628 8661
   "selectionElement": null,
8662
+  "shouldCacheIgnoreZoom": false,
8629 8663
   "viewBackgroundColor": "#ffffff",
8630 8664
   "zoom": 1,
8631 8665
 }
@@ -9219,6 +9253,7 @@ Object {
9219 9253
     "id9": true,
9220 9254
   },
9221 9255
   "selectionElement": null,
9256
+  "shouldCacheIgnoreZoom": false,
9222 9257
   "viewBackgroundColor": "#ffffff",
9223 9258
   "zoom": 1,
9224 9259
 }
@@ -9742,6 +9777,7 @@ Object {
9742 9777
     "id9": true,
9743 9778
   },
9744 9779
   "selectionElement": null,
9780
+  "shouldCacheIgnoreZoom": false,
9745 9781
   "viewBackgroundColor": "#ffffff",
9746 9782
   "zoom": 1,
9747 9783
 }
@@ -10191,6 +10227,7 @@ Object {
10191 10227
     "id4": true,
10192 10228
   },
10193 10229
   "selectionElement": null,
10230
+  "shouldCacheIgnoreZoom": false,
10194 10231
   "viewBackgroundColor": "#ffffff",
10195 10232
   "zoom": 1,
10196 10233
 }
@@ -10419,6 +10456,7 @@ Object {
10419 10456
   "scrolledOutside": false,
10420 10457
   "selectedElementIds": Object {},
10421 10458
   "selectionElement": null,
10459
+  "shouldCacheIgnoreZoom": false,
10422 10460
   "viewBackgroundColor": "#ffffff",
10423 10461
   "zoom": 1,
10424 10462
 }
@@ -10468,6 +10506,7 @@ Object {
10468 10506
     "id1": true,
10469 10507
   },
10470 10508
   "selectionElement": null,
10509
+  "shouldCacheIgnoreZoom": true,
10471 10510
   "viewBackgroundColor": "#ffffff",
10472 10511
   "zoom": 1,
10473 10512
 }
@@ -10517,6 +10556,7 @@ Object {
10517 10556
     "id2": true,
10518 10557
   },
10519 10558
   "selectionElement": null,
10559
+  "shouldCacheIgnoreZoom": false,
10520 10560
   "viewBackgroundColor": "#ffffff",
10521 10561
   "zoom": 1,
10522 10562
 }
@@ -10785,6 +10825,7 @@ Object {
10785 10825
   "scrolledOutside": false,
10786 10826
   "selectedElementIds": Object {},
10787 10827
   "selectionElement": null,
10828
+  "shouldCacheIgnoreZoom": false,
10788 10829
   "viewBackgroundColor": "#ffffff",
10789 10830
   "zoom": 1,
10790 10831
 }

+ 1
- 0
src/types.ts View File

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

Loading…
Cancel
Save