-
Notifications
You must be signed in to change notification settings - Fork 351
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
Proposed API changes: Promises, Web Workers, WebAssembly #113
Comments
'Not sure if this is in-scope here, but every time I've used this library I find myself rendering the graph as SVG, then doing a lot of DOM/CSS work to work with the graph dynamically. E.g. handle a click on a node, highlight connected nodes, etc. I.e. a high(er)-level API for working with an existing [svg] graph would be helpful. That said, I recognize that this might make more sense as an addon module rather than as part of the core. For bonus points, an API for modifying an existing graph and animating the changes would be slick. Again, probably better implemented as an addon. (e.g. a module that takes two SVG DOMs and figures out how to do the minimal set of operations needed to morph the first into the second would be a really cool, general-purpose, utility.) |
@broofa What about using D3 to work with the SVG? |
@broofa @mdaines d3-graphviz already utilizes viz.js and D3 to animate changes between one graph and another and I'm currently working on an API for modifying the graph that utilizes that animation (@broofa's bonus point) and an example application (that later might turn into a new D3 plugin) to show how to use it interactively. Enhancement requests with details are welcome as d3-graphviz issues |
My only issue with something like d3-graphviz is the D3 dependency. It's not small, and there's a lot of stuff in there that's orthogonal to this particular problem. I mean, I get it, d3 does some nice heavy lifting for DOM-manipulation, but it's not exactly a micro-framework. d3-graphviz is great if you're already using D3 but less so otherwise, is my point I guess. [Edit: I don't know what I'm talking about. See comments below] |
Since v4, D3 core is modular and d3-graphviz uses just a few of them. The size is almost negligible compared to viz.js. |
@magjac Ah, I see. Nice! Looks like minified+gzipped d3-graphviz is what, like 7-8K? Yeah, that's trivial. For anyone following along, a visualization of how d3-graphviz depends on a small subset of d3 core. |
@broofa I've opened magjac/d3-graphviz#40. Let's continue the discussion there and not pollute this thread. |
@magjac I'd certainly like to hear any ideas you have for making Viz.js work better with D3 in this discussion, since that would probably affect the API. |
@mdaines Absolutely. I just didn't want to hijack this thread for something it wasn't meant for (The possibility to build an API for modifying an existing graph and animating the changes as @broofa suggested above into d3-graphviz). I'm quite a newbie in the Javascript world so I probably won't be able to contribute so much knowledge about stuff outside of d3-graphviz. My implementation of web worker use in d3-graphviz was mostly trial and horror, but what I wanted to accomplish was that the viz.js script should be loaded when the page is loaded, but not JIT compiled until it's referenced. The reason being that otherwise, if it was going to be used in a web worker, it was compiled twice. There might be more clever ways to do this. If you'll add web worker support in Viz.js, I'll be happy to give you feedback and adapt d3-graphviz to it. I have been thinking of adding support for rendering a graph from data to d3-graphviz, but if you are going to implement it in viz.js, I'll use that. I wasn't aware of the Graphviz JSON output format. Even though it looks a bit odd, it would be nice to use it in order to be able to go back and forth between DOT and JSON. I had planned to look at dotparser for the same reason. |
@broofa I've added a draw API to d3-graphviz that allows you to modify an existing graph and animate the changes. Check out the D3 Graphviz GUI editor proof-of-concept made with it. |
Super excited about the proposed features especially webworker and webassembly. In fact, I am in an urgent need of a webworker supported version. If you can commit your progress, I can be your early adopter/tester. BTW: Will you be interested in adding a scalajs facade to this repo? I can provide you one. |
@mdaines Would it be possible to expose other parts of Graphviz through Viz.js? I'm not yet sure exactly which function I would need, but perhaps shape_desc *bind_shape(char *name, node_t * np). |
@thari The gh-pages branch of this repository uses Web Workers, but doesn't define a reusable API or anything like that. The solution is just "have a web worker that replies to messages with the result of calling Viz()". I'm working on an update to that branch that implements some of the ideas here, including using workers and returning promises. A scalajs facade is welcome; just open a pull request, or an issue if you prefer. Do you know if there's a way to provide "tests" for this, like with the TypeScript declaration? https://github.com/mdaines/viz.js/blob/master/test-types/viz-tests.ts |
@magjac I think it would be possible. I have thought about that, but I'm not sure I want to do it with this library, since I like the idea that it's more like the Graphviz command-line. But I can imagine a different, lower-level library that would do that. I haven't really worked with custom shapes -- is it possible to use the DOT |
@mdaines Thanks for considering my idea and for your suggestion. I realized I wasn't at all clear about what I wanted to achieve, which was kind of opposite to your suggestion. What I wanted to do was to retrieve data about how Graphviz draws its standard shapes in order to be able draw an exact copy of such a shape on top of a graph already laid out by Viz.js and then call Viz.js again and let the drawn shape make an animated transition into the new layout. You can see this in action in the D3 Graphviz GUI editor proof-of-concept for the simple ellipse and box shapes. I've started to work on more complex shapes, but already fairly simple shapes like the triangle and the pentagon pose some difficulties, not to speak of the even more complex ones further down the Node Shapes list. However, I've experimented with another approach which uses Viz.js to create an extra, temporary SVG for a graph containing only the shape I want to draw and then, after translating the coordinates, insert that shape into the graph. This seems feasible since Viz.js is fast enough to do a "layout" of a single-node graph without adding a noticeable delay for the user. Again, thanks for considering the idea. |
@magjac That looks very interesting! I'm not sure how you're accomplishing the transition, but I would have expected it would be possible to extract the SVG element you're interested in by selecting it using |
@mdaines Sorry, I don't think I really understand your question. I'm using d3-transition for the transition and d3-selection to select and extract the SVG element I'm interested in. Under the hood d3.select() uses |
@magjac I was wondering why you need more information from Graphviz about how it draws its shapes and what information you're interested in getting, since you can query for the elements using D3 or |
I've posted a proof-of-concept here: https://github.com/mdaines/viz-ui This is a reworking of the current Viz.js website using a vanilla Create React App project. The relevant API is in this directory https://github.com/mdaines/viz-ui/tree/master/src/viz and I make use of it in https://github.com/mdaines/viz-ui/blob/master/src/Graph.js Usage boils down to something like this: import Viz from './viz';
import workerUrl from './viz/viz.worker';
let viz = new Viz({ worker: workerUrl });
let src = 'digraph { a -> b; }';
viz.renderString(src, { format: 'plain' })
.then(str => console.log(str));
viz.renderSVGElement(src, { engine: 'circo' })
.then(element => document.body.appendChild(element));
viz.renderImageElement(src, { scale: 1 })
.then(element => document.body.appendChild(element)); This is a departure from the current single function API, but my thinking is that it shows better what's going on, since Viz now holds on to an instance of Worker. The odd |
@mdaines I want to be able to instantly draw a new node shape on top an already existing graph without having to let Viz.js compute a new layout immediately. Then, sometime later, I let Viz.js compute the new layout and let the old graph transition into the new layout. In my first approach (which I have now abandoned), I needed the information in order to be able to draw that new shape correctly by inserting SVG elements directly. I couldn't query it since at that point it didn't exist yet. In the new approach that I've now taken (described above), I don't need that information directly from Graphviz, since I'm creating an extra, temporary SVG, from which I can retrieve it (as you correctly point out above). |
@magjac I see! Sounds like a good approach. Maybe somewhat in the spirit of Viz.js also. 😄 As far as deeper access to Graphviz, one place I can see a possible benefit would be providing input as something other than a DOT string. That could mean exposing the Agraph stuff somehow. |
@thari I am a newbie in ScalaJs. I wonder if you could help with a facade of d3-graphviz. If so, that will be much better |
@yuanqingfei I am still, trying to find time to work on the promised Scala.js facade for this library. Although I am proficient in Scala, I am new to js and web workers. I am sure it will be fun to build a facade for d3-graphviz however, I don't think I can work on it any time soon. Sorry to pollute here :( |
I think 2.0.0 has settled down a bit at this point, so I'm going to close this. Please check out the latest prerelease in the Releases section or on npm and open a separate issue if you have feedback. |
Hi everyone. I'm considering some API changes for future Viz.js versions and I wanted to get your feedback.
The goals of these changes are:
Secondarily:
Here's what I've come up with so far:
Viz()
function in favor of format-specific rendering functions under theViz
namespace.module
option. This is a path to a file that contains the code generated by Emscripten, with a wrapper that allows it to be used as a worker or included as a<script>
tag.Promise
.Here's what rendering SVG might look like:
Or specifying the graph as an object:
To use the "lite" version, you'd use
"viz-module-lite.js"
instead.To use without a Web Worker, you'd include the module script and omit the
module
option. The return value would still be a promise.I think that in webpack, you'd probably use file-loader to get a path to the module you want. This way, webpack only looks at the wrapper or support code when bundling Viz.js, which is much smaller than the code generated by Emscripten. This is what it might look like:
This is the interface I have in mind:
The text was updated successfully, but these errors were encountered: