magjac / d3-graphviz

Graphviz DOT rendering and animated transitions using D3
BSD 3-Clause "New" or "Revised" License
1.67k stars 103 forks source link

Enable d3-graphviz API to set graph attributes in the DOT source #289

Closed GrahamHannington closed 11 months ago

GrahamHannington commented 11 months ago

Background to this suggestion

My own answer to my Stack Overflow question "How can I draw SVG diagrams that dynamically resize to fit the width of their HTML container, but with fixed-sized text?" uses HTML and JavaScript to inject width and height values into the size graph attribute in the DOT source.

The idea is to render a diagram that fits the width of its HTML container while maintaining the original scale of the diagram. In particular, so that the size of text in the diagram matches the size of body text in the HTML page.

Suggestion

Enhance the d3-graphviz API to streamline this use case.

Perhaps, something like:

.graphviz()
  .graph.setAttribute("size","4,3")
  .graph.setAttribute("ratio","fill")

where "4,3" is the width and height of the HTML container of the graph, more typically provided using variables rather than a literal string value:

  .graph.setAttribute("size",(graphContainer.node().clientWidth / 96).toFixed(2) + "," + (graphContainer.node().clientHeight / 96).toFixed(2))

or even, equivalently but much more concisely, without having to explicitly set the attribute values or refer to the container:

.graphviz()
  .fillContainer(true)

If you would prefer to deliberately steer well clear of having the d3-graphviz API manipulate the DOT source, and instead leave that to the user: no problem, I understand. I thought it was worth asking.

Related: if the DOT source specifies the same attribute more than once, I think the last one "wins". I can't find a statement to this effect in the Graphviz docs, but in practice, it seems to be true. So, d3-graphviz wouldn't have to actually edit attributes; just append attributes before the closing brace of the (di)graph.

GrahamHannington commented 11 months ago

There might be related use cases that require setting the graph size to match the HTML container size without also setting the graph ratio to fill. Maybe, to expand, or not specify a ratio at all. However, such use cases don't seem clear to me right now; I can't articulate them clearly. Still, perhaps it might be best to decouple:

Perhaps:

.graphviz()
  .graph.fitContainer(true)
  .graph.setAttribute("ratio","fill")

(I'm aware of the existing graphviz.fit.)

magjac commented 11 months ago

Thanks for the suggestion, but as you say, I prefer to stay away from manipulating the DOT source.

You might be able to achieve what you want with graphviz.width(), graphviz.height() and/or graphviz.scale().