I am trying to draw a graph using D3 where the nodes are rectangular. Then, for some reason, I need to find out the coordinates of those drawn nodes to draw the edges between the nodes. How can I get the coordinates of these rectangular nodes? I have tried doing this:
var ID = d3.select("#node_1")
.getBoundingClientRect()
.data(graph.nodes);
Here, I am using d3.select("#node_1") for selecting the particular node with ID node_1. But this getBoundingClientRect() does not seem to work in this case. What should I do?
Related
When I use
layer.findOne('#'+mynode).x()
this gives me the X position of the mynode, but only when mynode is ungrouped. If I group it, then it is not updated when the group is dragged.
When I use
absolutePosition()
method for a node - it works (returning the realtime position of a node), but only to the point when the view is moved or zoomed. Then the layer coordinates are no longer aligned with the absolute coordinates, so when I draw a line between nodes on the layer using those absolute coordinates, the line does not stick to the nodes.
So, how to get the position of an object that is in a group, but measured within its layer - so that I can use them to draw a line between nodes on that layer.
You can use node.getAbsolutePosition(layer). That function will return the absolute position of the node relative to the passed container (layer).
I've written some code which determines when user clicks on a polygon near to edges. I collect the mouse coordinates and want to add this point to polygon. For this, I'm adding points to poly.array().value on proper location. But I'm not able to understand how should it be reflected on the screen.
Sample code
poly.on('mousedown', function(event){
var points = myCanvas.point(event.x, event.y);
var polyArray = poly.array().value;
polyArray.splice(i+1, 0, [points] );
});
Possible approach that I can think (seems a hack not the proper solution) is to add points to polygon SVG element manually. I was wondering if there is a method in svg.js element to update the element and replot it.
I checked the source code of svg.draw.js, and found that there is a method plot which can re-plot the polygon with new points poly.plot(polyArray);
I'm new to SVG, so I don't know if I'm missing something obvious and simple.
In every lesson on creating SVG elements, x and y coordinates must be explicitly set for element to be drawn. But is there a way for a browser to draw one svg shape right next to another, without explicitly specifying coordinates, like DOM does when you write <div>content1</div><div>content2</div>?
What I want is:
Having a collection of data for elements (let's say, they are all rectangles with only width and height specified), is there a way to draw all of them sequentially in a row (horizontally)? I don't want to manually set coordinates for each element, just call foreach element in array and expect browser to figure out coordinates from each element's width property.
Is this achievable only with some script that dynamically calculates bounding box for each element or there is some simpler way?
I used d3 v4 and this technique (slightly modified) to draw a convex hull around nodes in a force-directed graph. Works great, but now I want to label these groups of nodes. Ultimately, I'd like to draw something that looks like this SVG. Is it possible to add a text element to a convex null polygon, so that it would move around as the polygon was moved, or would I need to create a separate grouping of some sort?
I would approach the problem like so:
Create a convex hull polygon from the points
Find the centroid of that polygon using d3.geom or d3.polygon (depending on version)
Update some text with that new coordinate at it's center
In d3 v4, this looks something like:
var polygon = d3.polygonHull(vertices);
Then you find the centroid:
var centroid = d3.polygonCentroid(polygon);
And update the text:
text.attr("transform","translate("+ centroid +")")
In d3v3 and v2 the code might look more like:
var polygon = d3.geom.polygon(d3.geom.hull(vertices));
var centroid = polygon.centroid();
text.attr("transform","translate("+centroid+")");
As for updating multiple texts at once, there's a bunch of potential methods to accomplish this, so I won't speak to it here.
Here's an example of a single text element being updated in v4.
I have a plot in D3 where I draw some circles and then some ellipses afterwards to show the median. I have a 1.5 second delay on my median, to try and draw it after the circles have appeared, but I still run into problems.
Here is a screenshot of an example: http://puu.sh/8csEK.png
The circle to the far right are behind it's median, the rest of the circles are all in front. When areas are crowded you cannot see the median anymore.
I have even tried using the following on transitions of my circles, but it's no use:
.each("end", <call function to draw ellipses>)
So my question is, how do i make sure that my ellipses are drawn on top of my circles?
I have a function that draws my ellipses and a function that draws my circles right now.
I'm assuming that you're using SVG to render your elements. In SVG, the display order is the order of drawing/appending to the DOM. That is, the element you append first is drawn at the back, the element you append last at the front. Child elements (e.g. something underneath a g) are drawn when their parent elements are drawn.
To make sure that groups of elements have the right order, it's usually easiest to add them to different SVG groups that are drawn in the right order. In code, this looks something like this.
var circles = svg.append("g");
var ellipses = svg.append("g");
// ...
ellipses.append(...); // this element appears in the front although it is drawn
// earlier because it is appended to the group appended last
circles.append(...); // this element appears behind the one appended to ellipses