AngryLoki / wikidata-graph-builder

Visualize Wikidata items using d3.js
https://angryloki.github.io/wikidata-graph-builder/
MIT License
187 stars 24 forks source link

Reasons to choose canvas? #12

Open wirekang opened 1 month ago

wirekang commented 1 month ago

Hi, we are considering to migrate to elkjs from dagre. I saw your comment(https://github.com/kieler/elkjs/issues/141#issuecomment-1418664010), this is great demonstration for us. I'm wondering why did you choose the canvas for rendering rather than svg? Since we need to support animations in our graph, svg is proper choice for us due to ease of css-transition. But I want to know are there any limitation that blocking svg or advantages when using canvas. Thank you!

AngryLoki commented 1 month ago

Hi, actually the first version from 2016 used svg. It was based on D3.js, which was mostly monolithic and SVG-based back then.

In the first version there were no direct graphs, and only force-based layouts were supported, which meant many redraws, until springs are stable.

Later on D3 added support of canvas (well, maybe it is more precise to say that it become media-agnostic). Rewriting wikidata-graph-builder with canvas significantly improved performance due to multiple reasons: 1) with SVG every graph node was DOM node with its own hover/click handlers, and DOM manipulation is generally slower than js objects 2) as there is no "hover over text" events for canvas, to detect hovering, I used shadow canvas, where each block of text is replaced with rectangle. After that, calculating node under cursor is trivial. Meanwhile, SVG used more precise calculation for each letter (but it was slow) 3) elkjs and other similar libraries may freeze UI when launched in the main thread, so I looked for solutions which can work in WebWorker. And given that coordinate calculation was done within WebWorker, why not to draw canvas there too? Such thing is not be possible with SVG. It allowed to fully eliminate data transfer between main window and worker: data is fetched, transformed, layout-ed and drawn fully inside WebWorker.

What was lost during svg->canvas migration: 1) precision of click on text 2) right-click -> save svg (but it did not work great anyways, as I used CSS properties that were not compatible with editors like inkscape)

However, when your graph is not force-based (and you don't care about FPS for redraw), and unprocessed data is small, SVG should still work fine.

wirekang commented 1 month ago

Thank you very much!