mdaines / viz-js

Graphviz in your browser
https://viz-js.com/
MIT License
4.1k stars 353 forks source link

Get image and image map #259

Closed cwellsx closed 1 month ago

cwellsx commented 2 months ago

I'd like to have both, an image (e.g. svg) and image map (e.g. cmapx) -- so that the resulting image can have clickable areas.

Graphviz's image map is useful because it's about 5 pixels in width along/around each edge -- i.e. much wider than the 1-pixel edge itself, and therefore easier to hit/click with the mouse.

My problem is that the API lets me specify one format at a time, not two:

When I do the same by invoking dot.exe from the command-line, I can tell it to output both at once:

const args = [dotFilename, "-Tpng", `-o${pngFilename}`, "-Tcmapx", `-o${mapFilename}`];

By the way, thank you for doing this project. Even without the optimization I'm asking for, it's faster (and so more interactive) than the command-line -- taking an unreasonably complicated graph of 50+ nodes, for example:

Given that I currently need to do it in two operations, I could reduce the apparent delay by making it progressive: display the SVG a.s.a.p., and then the image map a bit later when it's ready.

mdaines commented 2 months ago

Thank you for the suggestion. I hadn't thought about this use case, but it makes sense.

I'll think about how this could fit into the API. Accepting an array of formats and returning an array of strings would probably work.

At some point I'd like to offer a lower-level API where parsing, layout, and rendering are separate methods, which would allow reusing the layout for rendering multiple output formats.

For example (imaginary API):

const g = viz.parse("digraph { a -> b }");
g.layout("dot");

const svg = g.render("svg");
const imagemap = g.render("cmapx");

One complication is that this would need to deal with freeing the Graphviz context, graph, etc. when g is garbage collected.

cwellsx commented 2 months ago

From your description, I don't know why you'd also want a "low-level API" -- because you'd get what you said i.e.

reusing the layout for rendering multiple output formats

... if you allow an array of simultaneous formats in the high-level API call.

Maybe it's to save/reuse the time it takes to parse, if you then want to run several layout engines.

Thanks again! It's already a happy improvement (over dot.exe) to see sub-second rerendering responsiveness.