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

use Canvas instead of SVG for main view #933

Open
dave-doty opened this issue Sep 3, 2023 · 1 comment
Open

use Canvas instead of SVG for main view #933

dave-doty opened this issue Sep 3, 2023 · 1 comment
Labels

Comments

@dave-doty
Copy link
Member

dave-doty commented Sep 3, 2023

This is among the core design decisions made in 2018 that, in retrospect, was a mistake. When there are hundreds of thousands of components, rendering SVG fundamentally takes a long time.

To see that rendering SVG is a bottleneck even without all the other scadnano code (e.g., React virtual DOM computation, DOM updates, object comparison, Redux reducer/middleware computation), simply export a very large scadnano file main view to SVG and open in Inkscape. It's quite slow to render in Inkscape.

A better decision would have been to use HTML Canvas, which renders much faster than SVG. I mistakenly thought

  1. There's no way to easily track objects rendered in Canvas, e.g., to respond to pointer clicks.
  2. There's no way to use React inside of a Canvas.

Both these are false since there are libraries such as React Canvas that help with precisely this. In other words, although the HTML Canvas element does not natively track the objects you render in it, there are libraries that do this so as to have click-handlers, etc. (Although React Canvas appears to be abandoned, not updated since 2017, but perhaps there's an alternative such as Konva and react-konva.)

We should be able to use the React Canvas library similarly to how we use the React Bootstrap library for the Menu. (See the file lib/src/view/react_bootstrap.dart to see how the bindings are set up, in addition to the line <script src="external-libs/react-bootstrap.js"></script> in web/index.html.)

Now, there may still be some difficulty here. For instance, when we use a box select or rope select, we reach outside of React and get the HTML elements directly to test for intersection to see what objects were selected. It would be a shame to get months into implementing this only to discover there's no way around some issue like that.

This issue is likely to be so challenging that I made up a new label "extremely challenging" just for it. Step one is to use this page to brainstorm issues to think about and test for (e.g., how to do box/rope select within a Canvas, where the key challenge is that it relies on their being a real actual DOM element with a unique id that we can search for, with a bounding box calculated by the browser that we can compare to the box/rope we drew).

Incremental adoption: It would be great if we could figure out a way to incrementally adopt this. For example, perhaps we can maintain SVG and introduce some Canvas components as foreignObject or something, then gradually build up how much is rendered as an SVG foreignObject. But I predict this will either not work, or be too slow to really use, and we'll have to do a wholesale swap-out of Canvas for SVG.

@dave-doty
Copy link
Member Author

dave-doty commented Sep 3, 2023

Challenges

Here we identify key challenges that should be explored in a small test project before committing to doing this in scadnano.

  1. Box/rope select: This currently relies on putting a unique id string in each HTML element representing a selectable object in SVG. When doing box/rope select, we step outside of React and ask the browser for these elements directly, to compare their bounding boxes (computed by the browser) to the box/rope polygon we drew.
  2. Styling: We use CSS styles heavily on SVG objects. Presumably there's a workaround but it will require a lot of work to translate if we can't simply label an object with a CSS class like we do now.
  3. Arbitrary SVG paths: Presumably it's straightforward to find equivalents of rectangles, circles, polygons, etc. in Canvas. But in a few places we use more sophisticated SVG paths, which will have to be reproduced in Canvas somehow.
  4. Export SVG: Currently it is relatively straightforward to export an SVG file. This may not be easy even with a library like Konva. (or maybe they support it??)
  5. TODO:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant