I'm using the tree layout and code similar to http://mbostock.github.io/d3/talk/20111018/tree.html
I modified it for a top down orientation.
As each node is opened/expanded, the other open nodes compress to fit everything within the SVG element. Is it possible to prevent that? I would think modifying the x component of each node would be the approach but have not been able to accomplish that. The nodes move over, but are still compressed together.
Also wondering how to change the linking lines from a bezier to right angles/straight lines. Perhaps a separate question is needed.
The compression is automatic in the tree layout (and part of its point). There's no way to turn that off. However, you can simply make your SVG large enough to contain the entire expanded tree without compression. Note that this means that unless your screen is large enough scroll bars will be displayed even when everything that is visible fits onto the screen.
The links connecting the nodes are generated using the diagonal line generator in the example. In principle, you can replace this with any other line generator (e.g. d3.svg.line), but in practice some changes will be necessary because the diagonal line generator accesses source and target nodes in a special way. For a normal line generator, you would need to convert this structure to a two-element array and for each element specify how to access x/y coordinates. Then you can use any of the interpolations to get the curve you want.
Related
How can I draw a Bezier Line between two non-static DOM elements, like this:
The two lines should be drawn between the
<div class="brick small">Line starts here</div>
and the
<div class="brick small">Line ends here</div>
of this CodePen: https://codepen.io/anon/pen/XeamWe
Note that the boxes can be dragged. If one of the elements changes its position, the line should be updated accordingly.
If I'm not wrong I can't use a canvas, right? What can I use instead?
Let me point you toward the answer I beleve you're looking for, it's a dom element type called 'SVG' which is supported by most if not all web browsers of today (so you won't need to plug in anything external), in which you can draw lines, shapes, apply graphical filters much like in Photoshop and many other useful things, but the one to be pointed out here is the so called 'path', a shape that can consist of both straight lines with sharp corners, or curved lines (bezier) or both combined.
The easiest way to create such paths is to first draw them in for example Illustrator, save the shape in the SVG format, open that file in a text editor and pretty much just copy the generated markup code and paste it into your html, as it is supported there. This will result in the drawn shape to be displayed on your site. But in your case, you won't come around the a little bit complex structuring of the paths, because you wish to have control of it using javascript, so I would suggest first making a few simple paths in this way by exporting from Illustrator, study these in code, then manipulate their bezier values in javascript until you get the hang of how they work, once you've done that you will be able to create the accurate bezier shape you have in mind and (knowing the positions of the elements you want to connect) position them so that they connect your boxes.
Paths can even be decorated with markers, like an arrowhead in the end or beginning of the path, you can even design your own markers as you like them to look and much more if you would dig deeper into it.
Good luck! :)
I am currently using Cytoscape.js to display a variable amount of nodes using the circle layout. I now want/need to add additional groups of nodes around the original circle, with each group also represented in a circle layout.
The resulting visualization would look something like this:
(where each circle is a circle layout of nodes)
The additional groups don't necessarily need to be directly around the original layout, as the amount of circles also varies. I mostly just need to position the layouts such that they don't overlap each other.
I was able to add the additional groups as individual layouts, but I am unsure how to go about positioning them. I checked the docs and unless I missed something obvious, I didn't see how to accomplish what I need. Any pointers in the right direction would be appreciated!
Specify the boundingBox of each layout to tell it where the bounds of the nodes in the layout should be. Specifying a boundingBox tells the layout to put the nodes within the box. Make sure to specify adequate space and set your overlap-avoidance options appropriately. Overlap avoidance can make a layout need to use more room than it has allotted to it.
I am trying to make a visualization using d3 which is basically a scatter plot with links between the points. (I have attached a .gif of the existing java based visualization)
The points can be added by double clicking other points. On hovering over a point, I wish to have links drawn between the point and all its partners on screen.
I have the part where on double clicking a node, its partners are added. What I need help with is drawing the links (primarily I am not able to understand how can I get the x1,y1,x2,y2 values required to draw the links).
This is what my DOM looks like:
I have seen a lot of examples online but somehow not able to figure the solution - if anyone could link me to a similar visualization or share a fiddle/ give some pointers on how this can be achieved I would be really grateful.
First the simple stuff: here are 2 mechanisms for drawing the lines.
Next, in terms of the data representation of the lines, check out how links are typically drawn when working with the force directed layout.
Important: Do not get distracted by the existence of the force layout in this example and by the fact that the force layout works with these links (which are passed into it by calling force.links(links)). That aspect of the example probably doesn't have an equivalent in what you're trying to achieve.
However, do notice how the links array is constructed —— with each element of the array being an object with pointers to source and target datums. In your case, you'll want to work with a similar links array, where source is the node under the mouse and target is a node that's connected to it. So you'll end up with an array of links who all have the same source datum but unique target datums.
You can then bind the links array (via the usual .data() method) to a d3 selection of line or path elements. Once you bind, you can use the usual enter, update, exit pattern to append, update and remove (on mouse out) the drawn lines.
Given a source and target datums, you can calculate the x and y of the endpoints in the same way you currently calculate the translation of each <g> element, presumably using a d3 scale.
I am doing visualization with the JavaScript InfoVis Toolkit, in particular the hypertree. I am loading data dynamically and sometimes the labels around the nodes overlap and clutter. I would like to avoid this clutter by altering the label positions.
Here is an example of cluttering (the top and bottom nodes):
I imagine that I would loop through each x,y coordinate, give it some bounding box and do basic collision detection, and update positions accordingly.
For this library, I see the demo shows a onPlaceLabel() function, but (if I understand correctly) at that moment I wouldn't know the position of every other node's label. So, I am looking at onComplete(), where I see I can access each node as follows:
onComplete: function(){
ht.graph.eachNode(function(n) {
console.log(n);
}
}
But the node information does not include its label positions, only their positions relative to the center node. Is there a way to access the labels in this way and be able to update their positions?
I need to use the D3 Zoomable Icicle example (http://bl.ocks.org/mbostock/1005873) to view a file hierarchy.
I would like to have thumbnails to visualize the "leaf nodes" or "files".
I am not sure if this is possible using the example, and then if it is, how to go about having a different visualization of the folders and files within this layout? I have no idea how to attempt this.
Thanks.
If you implement your nodes as <g> elements, then you can use an .each() call to add either a rectangle or an <image> element and set it's size based on the data.
However, if you have lots of leaf nodes in a partition layout, the partitions tend to end up quite narrow, so the size of your image might be uselessly small. I see from your mock-up that you're hoping to tile the thumbnails in a multi-line grid. You're going to need to create some custom layout code, that identifies all the files (leaf nodes) within a given parent folder and calculates the amount of horizontal space which they collectively take up, then assigns the thumbnail positions into a grid no wider than that space.
You'll also need to make sure that your partition layout is sorting the partitions so that all the leaves are together, separate from any subfolders. I think the default sort should work this way, but it's something to keep in mind.
To make your updating and layout code straightforward, once you calculate the new positions for these leaves, make sure you save the x,y, dx (width) and dy (height) values in their respective data objects, over-writing the position and size created by the partition layout.