magjac / d3-graphviz Goto Github PK
View Code? Open in Web Editor NEWGraphviz DOT rendering and animated transitions using D3
License: BSD 3-Clause "New" or "Revised" License
Graphviz DOT rendering and animated transitions using D3
License: BSD 3-Clause "New" or "Revised" License
I raised this ticket in viz.js project orginally. But cannot wait see it resolved. Don't know you can help. Thanks.
This works (renders the graph in data
):
d3.select("#graph").graphviz().renderDot(data);
So does this (as above, with an anonymous callback function), except that I don't get a console message; renderDot does not trigger the callback:
d3.select("#graph").graphviz().renderDot(data, function(){console.log("Ended")});
I'm interested in using a callback function because I want to zoom the graph to fit the viewport. That's what I want to do in the callback (although, I'm still working out the "zoom to fit" function).
I'm using latest Google Chrome on Windows 10.
In case it's related, the Chrome console shows the following error (which doesn't seem to affect the rendering):
Invalid asm.js: Function definition doesn't match use - viz.js:37
Software versions:
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/[email protected]/viz.js" type="javascript/worker"></script>
<script src="https://unpkg.com/[email protected]/build/d3-graphviz.min.js"></script>
d3.select("#graph").graphviz()
.renderDot(dotSrc, function () {
console.log("XXX-0"); // <-- not called
});
There is no "XXX-0" in the console.
d3.select("#graph").graphviz()
.dot(dotSrc, function () {
console.log("XXX-1");
})
.render(function () {
console.log("XXX-2"); // <-- not called
});
Only "XXX-1" is printed.
The viewBox
attribute contains the string viewBox
which it shouldn't.
At least in Firefox it works anyway, but the warnings are annoying.
It would be great if you could add the ability to set/limit the extent of the zoom.
If an attempt to change the layout engine is made after rendering the first graph, d3-graphviz throws Error: Too late to change engine
.
Although this implementation was intentional and aimed at informing the user that a change of the layout engine between a call to graphviz.dot and graphviz.render had no effect, it was a bad idea since it prohibits transitions between two graphs rendered with different layout engines.
Rather than throwing an error, such a change should be allowed and its effect properly documented.
The error message is:
TypeError: prevStartShape is undefined
Local example:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="../node_modules/d3/dist/d3.js"></script>
<script src="../node_modules/viz.js/viz.js" type="javascript/worker"></script>
<script src="../build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>
var dotIndex = 0;
var graphviz = d3.select("#graph").graphviz()
.transition(function () {
return d3.transition("main");
})
.on("initEnd", render);
function render() {
var dot = dots[dotIndex];
graphviz
.renderDot(dot)
.on("end", function () {
dotIndex = (dotIndex + 1) % dots.length;
render();
});
}
var dots = [`
digraph {
node [shape="cylinder"]
a
}
`,`
digraph {
node [shape="cylinder"]
a -> b
}
`];
</script>
This problem can bee seen here
When growing edges are enabled (default), growing of edges to or from a node with an URL attribute causes the following error to be thrown:
"Unexpected tag: g. Please file an issue at https://github.com/magjac/d3-graphviz/issues"
Also, both the graph before and after the transition is shown,
The problem can be seen with this code:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/[email protected]/viz.js"></script>
<script src="https://unpkg.com/[email protected]/build/d3-graphviz.min.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>
var graphviz = d3.select("#graph").graphviz()
.fade(false);
graphviz
.renderDot('digraph {node [URL="DUMMY-URL"]; a; b}');
graphviz
.transition(
d3.transition()
.delay(1000)
.duration(1000)
)
.renderDot('digraph {node [URL="DUMMY-URL"]; a -> b}');
</script>
In the current implementation, if only one of the width and height attributes are specified, the unspecified attribute is automatically set to a value that preserves the current aspect ratio of the SVG.
Although this was a conscious design decision, it was a bad idea. If only one of the attributes are specified, the other should be left unchanged. The preservation of the aspect ratio is then taken care of by the preserveAspectRatio attribute. The default value of this attribute is xMidYMid meet
which in the case when fit is true, has the effect that the graph is scaled so that it is fully visible and centered in the direction where the SVG is larger than the graph itself.
Since the implementation is correct with respect to the current documentation, this might not be considered a bug and changing the functionality might not be considered a backwards compatible change of the API. I'm however going to do so anyway, because I think that the current functionality is not what you would expect, and release this as a patch release.
I like d3-graphviz very much for making the graphviz rendering available to d3. Would it be possible to give an example of how to implement actual user interaction with the graph? As simple as logging the name of a node to the console when I click on it (or a mouseover) would already be great... Thank you!
d3.select("#graph").graphviz(false);
yields the following error:
Uncaught TypeError: Viz is not a function
at Graphviz.initViz (d3-graphviz.js:796)
at new Graphviz (d3-graphviz.js:1931)
at Selection.selection_graphviz [as graphviz] (d3-graphviz.js:1974)
This is with the following imports:
<script src="https://d3js.org/d3.v5.js"></script>
<script src="https://unpkg.com/[email protected]/viz.js" type="javascript/worker"></script>
<script src="https://unpkg.com/[email protected]/build/d3-graphviz.js"></script>
It appears Viz
is undefined.
d3-graphviz works for me in latest Chrome and Firefox on Windows 10, but Edge (version 40.15063.0.0) fails to render the DOT and displays the following error:
SCRIPT5007: Unable to get property 'matrix' of undefined or null reference
d3-graphviz.min.js (1,1398)
(It occurred to me to look for an existing related issue for Viz.js, but I couldn't find one, so I thought I'd begin by reporting it here.)
Software versions:
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/[email protected]/viz.js" type="javascript/worker"></script>
<script src="https://unpkg.com/[email protected]/build/d3-graphviz.min.js"></script>
A drawn edge or node is drawn on the first SVG in the document, which is not necessarily the SVG rendered by d3-graphviz. When the edge or node is inserted into the graph, d3-graphviz renders it correctly, but it is still visible on the first SVG, at least partly.
Note that this bug affects the draw API only. Graphs are still rendered correctly from DOT source.
One case is when the second graph height changes. Another when the first graph has been panned or zoomed.
https://jsfiddle.net/fc4os5m0/8/
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="https://d3js.org/d3.v5.js"></script>
<script src="https://unpkg.com/[email protected]/viz.js" type="application/javascript"></script>
<script src="https://unpkg.com/[email protected]/build/d3-graphviz.js"></script>
<div id="graph"></div>
<script>
d3.select("#graph").graphviz()
.width(800)
.height(400)
.scale(0.5)
.fit(true)
.renderDot('digraph {label="Click me"; a -> b}')
.on("end", function() {
d3.select(document).on("click", function() {
var event = d3.event;
event.preventDefault();
event.stopPropagation();
console.log('document click');
render2();
});
})
;
function render2() {
d3.select("#graph").graphviz()
.renderDot('digraph {label="Pan me"; c; d}')
;
}
</script>
A workaround is to use a transition.
Version 0.1.3 works great with Browserify, but how to Browerify the latest version 1.1.0?
The problem is (I think) the way the webworker is used/created.
Does not seem to cause any problem, but is annoying.
Introduced in v1.6.1 in 118d232
When setting a node border to dashed, then transitioning to something without a dash, the original dash does not go away.
live example
https://jsfiddle.net/xpvt214o/99139/
The zoom behavior is needed e.g. when custom zoom event filtering shall be applied.
The error message is:
TypeError: guideData.attributes.points is undefined
Local example:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="../node_modules/d3/dist/d3.js"></script>
<script src="../node_modules/viz.js/viz.js" type="javascript/worker"></script>
<script src="../build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>
var dotIndex = 0;
var graphviz = d3.select("#graph").graphviz()
.transition(function () {
return d3.transition("main")
.ease(d3.easeLinear)
.delay(500)
.duration(1500);
})
.on("initEnd", render);
function render() {
var dot = dots[dotIndex];
graphviz
.renderDot(dot)
.on("end", function () {
if (dotIndex != 2) {
dotIndex = (dotIndex + 1) % dots.length;
render();
}
});
}
var dots = [`
digraph {
a
}
`,`
digraph {
a [shape="cylinder"]
}
`,`
digraph {
a
}
`];
</script>
Something like:
_selection_.graphviz({zoom: false, tweenPrecision: 10})
Hi everyone,
Try render this dot:
digraph X {
rankdir=LR;
"X" [label=Bob, shape=square, URL="Y", style=filled, fillcolor="#dd4477"];
"Y" [label=Bob2, shape=square, URL="Y", style=filled, fillcolor="#ff9900"];
"X" -> "Y" [label=Danser, labeltooltip=asdada];
}
When hovering the X -> Y edge, the tooltip is not displayed. Looking at the HTML it seems to be an order issue.
Move the g-tag for the label above all others in the rendered html and it works.
The current zoom reset functionality is instantaneous. This enhancement calls for a way for the user to specify a transition to be used during zoom reset in a way that can be supported by the public API, rather than using the internal variables of d3-graphviz as @GrahamHannington does in #21 (comment).
The default behaviour of Graphviz is to create an svg that just fits the contained graph.
These cases should be supported:
Special consideration may be necessary to handle the svg aspect ratio.
See https://beta.observablehq.com/@magjac/d3-graphviz#adot for a possible implementation.
Even this simple case with a div containing a text node with a newline does not work:
<!DOCTYPE` html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="../../node_modules/viz.js/viz.js"></script>
<script src="../../build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;">
</div>
<script>
d3.select("#graph").graphviz()
.fade(false)
.renderDot('digraph {a -> b}');
</script>
The error message in the console is:
TypeError: d is undefined
Hello,
First of all, please allow me to thank you for this wonderful package! I find it extremely useful for a project I am working on, and the graph transitions are beautiful. Thank you again for your hard work.
I ran into a small issue I wanted to bring to your attention, along with a possible fix. I'm using this library on a website I'm developing locally (not on a server) with web workers. As such, I believe the following line is used to to add the file://
protocol so the web worker can load viz.js
:
Line 23 in 12ba86a
For my local website, this tends to produce paths like file:///libs/viz.js
(note the three /
, thereby making it an absolute URL pointing to /lib/viz.js
relative to the root of my filesystem, instead of my desired relative directory, /path/to/local/website/libs/viz.js
. Then, the script does not load because the file does not exist. So, I wonder if this line may not be correctly handling that my website's root is not the same as my file system's root, for these local URL's.
I have a possible fix, using the URL API:
vizURL = (new URL(vizURL, document.location.href)).href;
With this change, I get correct paths like file://path/to/local/website/libs/viz.js
, and then the library works perfectly (I'm using Firefox, but haven't run any of your other tests).
What do you think about this change? I'm happy to answer any questions.
Thank you again!
The d3-graphviz source code uses a few ES6 language features which causes problems for and older browsers and certain build tools such as react-scripts.
In order to remedy this, the production build should be transpiled to ES5 before publishing it on npm.
This will fix #45.
This bug is valid when key mode 'title' (default) is used.
The zoom works after this:
var graphviz = d3.select("#graph").graphviz()
.renderDot('digraph graph1 {a -> b}', function () {
this.renderDot('digraph graph1 {a -> b; a -> c}');
});
The zoom does not work after this:
var graphviz = d3.select("#graph").graphviz()
.renderDot('digraph graph1 {a -> b}', function () {
this.renderDot('digraph graph2 {a -> b; a -> c}');
});
The reason is that the zooming is performed by changing the transform attribute on the top level g element that exists when the zoom behavior is created and this element is replaced by a new element when the graph ID is changed.
To be used to restore the original zoom level.
When growing edges are enabled (default), growing of edges to or from a node with a style attribute "wedged" causes the following error to be thrown:
"Unexpected tag: path. Please file an issue at https://github.com/magjac/d3-graphviz/issues"
Also, both the graph before and after the transition is shown,
The problem can be seen with this code:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="../../node_modules/viz.js/viz.js" type="javascript/worker"></script>
<script src="../../build/d3-graphviz.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>
var dotIndex = 0;
var graphviz = d3.select("#graph").graphviz()
.tweenPaths(false)
.tweenShapes(false)
.transition(function () {
return d3.transition("main")
.ease(d3.easeLinear)
.delay(500)
.duration(1500);
})
.logEvents(true)
.on("initEnd", render);
function render() {
var dot = dots[dotIndex];
graphviz
.renderDot(dot)
.on("end", function () {
dotIndex += 1;
if (dotIndex < dots.length) {
render();
}
});
}
var dots = [
`
digraph G {
node [
shape="circle"
style="wedged"
]
a [label="A", fillcolor="#d62728;0.4:#1f77b4"]
b [label="B", fillcolor="#d62728;0.6:#1f77b4", ]
}
`,
`
digraph G {
node [
shape="circle"
style="wedged"
]
a [label="A", fillcolor="#d62728;0.4:#1f77b4"]
b [label="B", fillcolor="#d62728;0.6:#1f77b4", ]
a -> b
}
`,
];
render();
</script>
If event logging is enabled with .logEvents(true) and .transition() is not used, the following error is thrown:
TypeError: graphvizInstance._transition is undefined
Some arrowheads have the wrong direction during transitions and the edges are grown i segments. On Firefox is looks good.
The root cause is that the getTotalLength() method is undefined here and the test workaround for jsdom/jsdom#1330 kicks in. Probably this is because the element is part of a DocumentFragment.
The dot worker is loaded from ../src/dotWorker.js which works fine locally, but not when using outside the repository. For instance https://bl.ocks.org/magjac/f485e7b915c9699aa181a11e183f8237 does not work.
viz.js version 2.0 will have a new API based on promises, see mdaines/viz-js#113. d3-graphviz should support this API by any of these options:
Option 1. Backwards compatible adaptation to the new viz.js API in a minor version
Option 2. Breaking changes by providing a promise-based API like the one viz.js has in new major version
Before investigating this, I don't know which one is to prefer, but my guess is option 2.
Methods of the Draw API that accepts an attribute argument modifies properties of the supplied object. This may cause side effects that the calling function does not expect.
The methods should not do this. Instead they should make a copy of the object and modify that object.
Flushed with the success of removing the width
and height
attributes of the <svg>
to set the initial size of the graph to the viewport, I thought I'd try the new-in-v1.1.0 resetZoom
.
I get the following error message in the browser console (latest Chrome on Windows 10, using d3-graphviz v1.1.0):
Uncaught TypeError: Cannot read property 'call' of undefined
at Graphviz.resetZoom (d3-graphviz.js:69)
at Object.resetZoom (cpattl.html:95)
at HTMLButtonElement.onclick (VM1182 cpattl.html:80)
In d3-graphviz.js
, the _zoomselection
property of this
is undefined:
function resetZoom() {
this._zoomSelection.call(this._zoomBehavior.transform, this._originalTransform);
return this;
}
My JavaScript function, triggered by a button click:
dot2viz.resetZoom = function resetZoom() {
var t = d3.transition()
.duration(750)
.ease(d3.easeLinear)
d3.select("#graph").graphviz()
.transition(t)
.resetZoom()
}
where #graph
refers to the HTML <div id="graph">
that is the container for the rendered DOT:
d3.select("#graph").graphviz().renderDot(data, renderDotEnd)
I'm frankly not sure what I should be selecting to perform the resetZoom
:
#graph
#graph > svg
#graph0
(the ID of the first child <g>
of the <svg>
all result in the same error.
I suspect that this error is caused by me doing something wrong, but I can't work out what.
How do I trap errors in the DOT; that is, the data
that I pass to d3.select("#graph").graphviz().renderDot(data, myRenderDOTEndFunction)
?
I've read the the following in the viz.js readme:
If Graphviz encounters an error, Viz will throw an Error object with the error message.
and I've looked at the d3-graphviz code that calls Viz, but I can't yet figure out how to trap errors in the input DOT that I pass to d3-graphviz.
I see that the Graphviz object returned by d3.select("#graph").graphviz().renderDot(data, myRenderDOTEndFunction)
contains a _worker
property, and _worker
contains an onerror
property that has the value null
. I suspect I need to set that property.
I could burn time trying to figure out what to do next—I'm enjoying improving my JavaScript coding skills—but I need to crack on with other work.
P.S. I really like d3-graphviz. Thank you so much for this. I'm using d3-graphviz for what is, so far, a small internal-use-only project, but I hope to get management approval to publish my project as a GitHub repo, which will, effectively, be a showcase for d3-graphviz.
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
This is something I'm working on right now. This issue is open for anybody to have suggestions.
The problem can be seen clearly at the end of this demo if you try to interact.
This has been a known issue since the inception of d3-graphviz and thought to be unavoidable. Recent discoveries (I finally took the time to understand transition.tween) have however shown that it isn't.
The problem occurs when the transform of the top level g element is transitioned from one value to another, which occurs when the height of the graph changes. The same transform is used by the zoom functionality and when the panning or zooming occurs, it is immediately overwritten by the transition. After the transition, the transform is recalculated based on the current zoom transform and the correct value is set. This looks to the user as if the zooming or panning was queued during the transition.
I encountered a null reference error on Safari on Mac OS.
The error is as same as the one which occurs when I access demo page
I explored the code, and found
var matrix = transform.baseVal.consolidate().matrix;
in getTranslation() seems to be the cause of this error.
When creating a graphviz renderer instance on an element, if a graphviz renderer instance already exists for that element, that graphviz renderer instance should be returned instead of creating a new instance.
This is useful in cases where you don't have full control over when this takes place, such as in Observable.
See https://beta.observablehq.com/@magjac/d3-graphviz#adot for a possible implementation.
It would be great to add the ability to limit the graph from going off the screen.
(I couldn't resist writing "DOT-to-DOT" in the title.)
Transitioning from one DOT to another causes this error (latest Chrome on Windows 10, graphviz v1.1.0):
d3-graphviz.js:622 Uncaught TypeError: Cannot read property 'x' of undefined
at convertToPathData (d3-graphviz.js:622)
at extractData (d3-graphviz.js:730)
at SVGPathElement. (d3-graphviz.js:755)
at S.each (d3.v4.min.js:2)
at extractData (d3-graphviz.js:745)
at SVGAElement. (d3-graphviz.js:755)
at S.each (d3.v4.min.js:2)
at extractData (d3-graphviz.js:745)
at SVGGElement. (d3-graphviz.js:755)
at S.each (d3.v4.min.js:2)
The problem surfaces here:
var bbox = guideData.bbox;
bbox.cx = bbox.x + bbox.width / 2;
bbox
is undefined.
This error only occurs for some DOT files. Any idea what the problem might be?
I create a project with create-react-app and with d3-graphviz as dependency. However, when build, it always popup such kind of error:
react-scripts build
Creating an optimized production build...
Failed to compile.
Failed to minify the code from this file:
./node_modules/d3-graphviz/src/drawEdge.js:14
Read more here: http://bit.ly/2tRViJ9
It seems that some code in d3-graphviz fail to ES5?
The resetZoom() method resets the zoom transform to the original transform of the first rendered graph, which is incorrect after a second graph has been generated on the same element. The reset needs to use the original transform from the last generated graph.
The problem can be seen in this example.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.