I am writing an animation using d3, and I cannot seem to find a way to easily ensure that a graphic always appears "behind" other graphics.
Specifically, I am dealing with lines and circles (imagine a directed graph), and it sort of looks bad to have some of the lines on top of the circles, and others underneath. Is there a way to set the z/depth of certain graphics, in this case my lines, manually? I apologize if this seems google-able, but I attempted typing "graphic depth d3" and other variations and got nothing.
EDIT : Accepted answer works, a more detailed description of the problem can be found here.
SVG doesn't have a z-index property or similar, the elements are drawn in the order in which they appear in the DOM -- elements higher up are drawn behind elements that have been added afterwards.
The easiest way to group elements into layers is to use g elements. So in your example, I would use two g groups, one for the lines and one for the circles. Add the g for the lines first and then all of the lines underneath it. If you then add the circles to the second g that you added afterwards, all circles will always be on top of all lines.
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.
By default, Highcharts fills horizontal legends with legend items from left to right, introducing a line break between items when the next item would overflow the legend's bounding box.
I would like to be able to control where such line breaks occur, so that (for example) instead of this:
I could visually group the "Target" and "Actual" items together, and then list the remaining series on subsequent lines like this:
Using useHTML and labelFormatter, I've tried a few different approaches involving <span>s, <div>s and styling to try to achieve this, but none of them have had any effect. The one approach I did manage to make work (from which I generated the second image above) is horribly kludgey, and probably can't be easily generalized for use in real code.
I'm thinking this ought to be a fairly simple thing to do, and I suspect that I'm merely overlooking some existing Highcharts feature that would do it.
Can someone point me in the right direction?
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.
Is there a good algorithmic way to combine multiple squares (each has four x/y points) to draw an outline of the joined figured in canvas?
The figures I would want to make sure work are as follows:
two squares joined to make a rectangle
four squares joined to make a larger square
two squares that are diagonal like a rectangle with triangles at each end at 45 degrees - this is probably the most irregular/special case...
three or four squares joined to make a concave shape like a Tetris(TM) piece 'L' piece
Is there an easy way to calculate the outer points to use to draw a line path (and maybe a filled figure) from all of the squares points?
Thanks!
Update: the reason we want to do this is because we want to show squares that are of the same group that are next to each other in a 2xn array specifically (but could also be 1xn in some cases). Maybe there is an easier answer if I just iterate through the different squares and form groupings some other way?
You're looking at it from the perspective of "I've got squares".
But you need to look at it from the perspective of "I've got points" (each square is just 4 points).
What you're actually looking for is called the "Convex Hull" - and the question has already been answered on SO here:
Polygon enclosing a set of points
I actually started diagramming your solution to go about solving it - and that's when this occurred to me.
I realized when I was making my diagrams that the outline of these shapes has several interesting properties - which is when I thought "yeah right - someone has already done this - this must be around already".
So I googled "construct smallest polygon enclosing other polygons"
And found the other S.O. question.
Although you do have two seemingly dis-similar requirements:
two squares that are diagonal like a rectangle with triangles at each
end at 45 degrees - this is probably the most irregular/special
case... three or four squares joined to make a convex shape like a
Tetris(TM) piece 'L' piece
In the first example above, you say you want the "Convex Hull".
But in the second example above (the tetris pieces), you'd need the "Concave Hull".
Good luck.
Here are my diagrams:
I'm curious as to why you'd want to do that.
In any case, my intuition is that you want to find is called "concave hull", but I'm no expert.
Check out this question and see if that's what you want.
Edit: also this question on gis.stackexchange.com