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

Pan/Scale to center graph? #7

Closed
badams opened this issue Nov 9, 2017 · 12 comments
Closed

Pan/Scale to center graph? #7

badams opened this issue Nov 9, 2017 · 12 comments
Assignees

Comments

@badams
Copy link

badams commented Nov 9, 2017

Is there any way to center the graph on the canvas and scale it to fit (if its too large), I imagine this would be done with the attributer somehow

@magjac
Copy link
Owner

magjac commented Nov 11, 2017

Yes, have a look at https://github.com/magjac/d3-graphviz/blob/master/examples/demo-grow-entering-edges.html#L10. You might want to set x = y = 0; scale = 1.0 or optimize them out completely.

Thanks for submitting this issue. If you are using this library, don't forget to "Watch" it to stay tuned for updates or even "Star" it if you like it.

You can also use Stack Overflow tags d3.js & graphviz to ask for help. Although I make an effort to assist everyone that asks, I am not always available to provide help promptly or directly.

@magjac magjac closed this as completed Nov 11, 2017
@magjac magjac self-assigned this Nov 11, 2017
@badams
Copy link
Author

badams commented Nov 12, 2017

That looks like it should work, I'll just need to calculate the scale based off the size of the graph vs container.

Really appreciate the support, this is a great library and will watch for updates

@GrahamHannington
Copy link

With apologies for this necropost (please feel free to direct me to post on this topic elsewhere), I've started looking into a "scale to fit" function, and have this early observation: in my browser's "developer tools" (I'm using latest Chrome on Windows 10), if I edit the d3-graphviz-generated <svg> element and remove its width and height attributes, then the SVG diagram (graph) scales to fit the width of its container, with aspect ratio preserved.

In my case, the container is an HTML <div> that occupies the entire viewport. Here's the corresponding CSS:

html, body, div#graph {
  background-color: #f5f7fa; /* Carbon: ui-02 */
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  margin: 0;
  overflow: hidden;
}

For my purposes, this is a good default/initial view of the graph. Next, I'm going to look at how to remove those width and height attributes. Possibly with attributer.

@GrahamHannington
Copy link

I'm now using a renderDot callback function (d3-graphviz v1.1.0) to remove the width and height attributes from the <svg> element (here, the dot variable contains the path of the DOT file):

function renderDotEnd() {
  /* Remove width and height attributes from svg element,
     so that it scales to fit its container */
  d3.select("#graph > svg")
    .attr("width", null)
    .attr("height", null)
}

// Load and render DOT file
d3.text(dot, function(error, data) {
  if (error) {
    alert("Error loading DOT file.")
  } else {
    d3.select("#graph").graphviz()
      .renderDot(data, renderDotEnd)
  }
})

I'd gratefully accept tips on improving this code. For example:

  • Should I be removing the width and height attributes after a different d3-graphviz event (using on)? In removing the attributes at this point (after renderDot), am I causing the browser to do a "double take" on the SVG, rendering it twice: the first time with width and height attributes, and the second time without? I can't detect any "flashing"/resizing.
  • In my renderDotEnd() function, is there a more elegant way to refer to the svg element than d3.select("#graph > svg")? Say, using this?

I deliberately ended up not using attributer, because the attributer function gets called for each SVG element (<svg> and all of its descendants). While I can see that would be very useful in some circumstances, here, I specifically want to target just the <svg> element. For that use case, an attributer function with, say, if (datum.tag == "svg") seems inelegant to me. (Which I realize might sound ridiculous coming from someone who just posted code with an alert for "error trapping"!)

SVG meet parameter value

In latest Chrome on Windows 10, this tweak—with the CSS cited in my previous comment—fits the graph to the width of the viewport, maintaining the aspect ratio of the graph. If the graph is too high to fit within the viewport, then the graph overflows past the bottom edge of the viewport.

That behavior is acceptable to me, but, after reading (and rereading) the MDN documentation for the meet parameter value of the SVG preserveAspectRatio attribute:

Scale the graphic such that:

  • aspect ratio is preserved
  • the entire viewBox is visible within the viewport
  • the viewBox is scaled up as much as possible, while still meeting the other criteria
    In this case, if the aspect ratio of the graphic does not match the viewport, some of the viewport will extend beyond the bounds of the viewBox (i.e., the area into which the viewBox will draw will be smaller than the viewport).

I can't help thinking that the behavior of Chrome is not meeting the letter of this specification ("the entire viewBox is visible within the viewport"; in Chrome, it's not).

I've just checked Firefox; same behavior as Chrome (fit to width; tall graphs extend past the bottom edge of the viewport).

Am I misunderstanding the description of meet?

@magjac
Copy link
Owner

magjac commented Dec 1, 2017

I'm afraid this might be a little over my head. I'll have a look at it during the weekend, but I do recommend you to use Stack Overflow to ask for help. Especially in this case, which does not seem to be d3-graphviz specific. In any case, a complete example would make it much easier to understand what you want to achieve and find a solution. See instructions below.

Thanks for submitting this issue. If you are using this library, don't forget to "Watch" it to stay tuned for updates or even "Star" it if you like it.

You can also use Stack Overflow tags d3.js & graphviz to ask for help. Although I make an effort to assist everyone that asks, I am not always available to provide help promptly or directly.

When asking for help, please include a link to a live example that demonstrates the issue, preferably on JSFiddle. It is often impossible to debug from code snippets alone. Isolate the issue and reduce your code as much as possible before asking for help. The less code you post, the easier it is for someone to debug, and the more likely you are to get a helpful response.

@GrahamHannington
Copy link

I'm reasonably happy with the behavior I get, now that I'm deleting the width and height attributes from the <svg> element. That pretty much fixes my problem; and, I think, provides an easy solution for @badams.

Regarding the meet parameter value: yes, this is not specific to d3-graphviz. While it's relevant to anyone interested in SVG "zoom to fit", nothing under that "meet" heading in my previous comment is specific to d3-graphviz, so I should probably have chosen somewhere else to write that. Sorry.

@magjac
Copy link
Owner

magjac commented Dec 1, 2017

@GrahamHannington No need to be sorry. I don't mind you posting here. It's just that I'm quite a Javascript noob myself and even more so an HTML, CSS and SVG noob, so I think you'd be better off asking at SO where there are plenty of non-noobs. That said, I am going to look at your post when I more time than I have right now.

@GrahamHannington
Copy link

Regarding my question in an earlier comment:

Should I be removing the width and height attributes after a different d3-graphviz event (using on)?

I increasingly suspect that the answer is "yes".

Why? Because I've moved on to experimenting with transitioning between DOT files (if that's acceptable terminology).

I see the smooth animation between graphs (from the original DOT to the new DOT), but that animation occurs at the scale dictated by width and height attributes on the new DOT. And then, after the animation, the scale flicks to "zoom to fit" (due to the callback on the renderDot). I'll readily admit it's the removable of those attributes that is "causing" the problem.

Is there an on event that marks the point at which d3-graphviz has created the <svg> element, but has not yet inserted it into the DOM? I'd like to remove the width and height attributes at that point.

@GrahamHannington
Copy link

I've tried all of the on events that I thought might be possibilities—layoutEnd, renderEnd, transitionStart, even dataProcessEnd—but none of them "works"; none of them sets the new graph to "zoom to fit" before the transition.

I'd appreciate advice here. I can see myself having to go back to the drawing board and rethink how I'm zooming to fit. But I really like how removing those width and height attributes makes the graph initially and dynamically (re)size to fit the viewport.

@magjac
Copy link
Owner

magjac commented Dec 1, 2017

You must use the .attributer() method to also update the data as described in the documentation. More precisely this line is needed.

During transitions, all attributes of every element in the graph is updated from the data. Explicitly modified attributes will be overwritten.

@magjac
Copy link
Owner

magjac commented Dec 2, 2017

@GrahamHannington I've look at your detailed questions above and you're clearly more knowledgeable than me regarding HTML and CSS. I don't think I can contribute with any insights without extensive research and learning.

I will however help you with the "zoom to fit" function if you provide a complete example on Stack Overflow. Please use both the d3.js and graphviz tags. I look at that combination every day.

@magjac
Copy link
Owner

magjac commented Jun 11, 2018

@badams @GrahamHannington: In v2.2.0 I've added support for resizing the SVG and fit and scale the graph within it without the need to use the attributer. Feel free to contact me on Slack if there's something you want to discuss.

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

No branches or pull requests

3 participants