tldraw / tldraw

SDK for creating whiteboards and canvas experiences on the web.
https://tldraw.dev
Other
33.4k stars 1.99k forks source link

[Bug]: laggy UI on fast scrolls #1762

Closed lakesare closed 10 months ago

lakesare commented 10 months ago

What happened?

We updated tldraw from 2.0.0-alpha.14 to ^2.0.0-canary.4bd8a257ac02 (current main basically), and we started seeing some artifacts that look like "lazy loading".

Before:

After:

How can we reproduce the bug?

  1. Create 100 shapes
  2. Scroll around back and forth reasonably quickly

What browsers are you seeing the problem on?

Firefox, Chrome

adi-lb-phoenix commented 10 months ago

i see this issue in 2.0.0-alpha.14 too .

lakesare commented 10 months ago

PSA: subclassing all components that are getting culled and setting override canUnmount = () => false works, to hell with performance 😄

image
adi-lb-phoenix commented 10 months ago

how'd you figure it out ?

lakesare commented 10 months ago

Oh they got rid of this line in 9-hours-ago commit (https://github.com/tldraw/tldraw/commit/e4829f67023df6097d06eef484305ca0c0faee44), it used to be like that:

image

That commit might be fixing this issue altogether though, needs to be checked.

adi-lb-phoenix commented 10 months ago

can you share the file name in the repo ?

lakesare commented 10 months ago

https://github.com/tldraw/tldraw/blob/e4829f67023df6097d06eef484305ca0c0faee44/packages/editor/src/lib/components/Shape.tsx#L121

steveruizok commented 10 months ago

That effect is actually by design!

We disabled it accidentally a few versions ago and have now restored it.

There are a few reasons why we do things that way.

If we leave everything in the DOM then there can be memory / performance issues when having lots of shapes in the project, even when those shapes are off screen. It's generally better to "cull" off screen shapes and instead only include the on-screen shapes in the DOM.

Unfortunately, mounting / unmounting shapes is also expensive. If we mount / unmount shapes as soon they appear on the screen or leave the screen, then we end up doing that expensive work during other expensive work—scrolling or zooming—which causes those interactions to be slow.

Instead, we wait until you've stopped zooming or panning before restoring the shapes. In the meantime, we display grey boxes which are placeholders for the "culled" shapes.

We could still make some improvements:

lakesare commented 10 months ago

requiring a certain number of shapes before we turn this effect on allowing a "developer" user to turn it off completely

I think these two would be great, especially the latter.

Our use case e.g. is always max 40 shapes and scrolling around is frequent and needs to be flawless/non-distracting.

steveruizok commented 10 months ago

Ok, I'm going to set it so that setting the Editor.renderingBoundsMargin to Infinity will keep all shapes on screen at all times (unless they're clipped by a frame).

lakesare commented 10 months ago

Thanks, does work in my code!

PSA - it looks like this:

const handleMount = (editor: Editor) => {
    editor.updateInstanceState({ isFocusMode: true });
    editor.user.updateUserPreferences({ isSnapMode: true });

    editor.renderingBoundsMargin = Infinity; // HERE
}

<Tldraw onMount={handleMount}/>