I have a code which plots lines and circles.
I know what does slice do below.
But when do we use slice vs non slice way of a variable in .data section?
var link = g.selectAll(".link")
.data(nodes.descendants().slice(1))
.enter().append("path")
.attr("class", "link")
.style("stroke", function(d) { return d.data.level;})
.attr("d", function(d)
{
return "M" + d.x + "," + d.y
+ "L" + d.parent.x + "," + d.parent.y;
});
var node = g.selectAll(".node")
.data(nodes.descendants())
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d)
{
return "translate(" + d.x + "," + d.y + ")";
});
var circle = node.append("circle").attr("r",30);
I take it you are using descendants() with d3.hierarchy - notice in the console output below that Eve has no parent because it is the 'root' node, and that all the other nodes in the descendants() array do have a parent.
const nodes = d3.hierarchy(data);
for (let d of nodes.descendants()) {
let name = d.data.name;
let depth = d.depth;
let parentName = d.parent ? d.parent.data.name : 'no parent - no link!';
let msg = `Name: ${name}; Depth: ${depth}; Parent: ${parentName}`;
console.log(msg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script>
const data = {
"name": "Eve",
"children": [
{
"name": "Cain"
},
{
"name": "Seth",
"children": [
{
"name": "Enos"
},
{
"name": "Noam"
}
]
},
{
"name": "Abel"
},
{
"name": "Awan",
"children": [
{
"name": "Enoch"
}
]
},
{
"name": "Azura"
}
]
}
</script>
Then note d function:
.attr("d", function(d)
{
return "M" + d.x + "," + d.y
+ "L" + d.parent.x + "," + d.parent.y;
});
Which says Move the the centre of the 'child' circle and draw the Line to the middle of the 'parent' circle. Because your 'root' node (Eve) has no parent then this node should be eliminated from the link layout hence slice(1). But because all the other nodes should be connected to Eve then this root node is not sliced from here:
var node = g.selectAll(".node")
.data(nodes.descendants())
In order that the circle for the Eve node is drawn and therefore the links from the child nodes of Eve can connect to something.
Related
I have a force layout that generates some node positions for a given node-link diagram. My task is to place these nodes and links to a radial scatter plot. The nodes should be placed in such a way that their distance from the center node can be visible. For this reason, I calculate the euclidean distance of the nodes from the center and find maximum value from the calculated distance. Then scaled the radius of the radial plot within 0 to maximum distance value. But when I tried This example, the node-link diagram did not place upon the scatter plot. My question is how can I place the node co-ordinates to the plot such that the distance of the nodes from the center node can be seen by the circle line of the scatter plot.
Here is a portion of my input data
{
"nodes": [
{
"id": "A0",
"group": 0,
"degree": 19,
"name": "x"
},
{
"id": "P0",
"group": 0,
"degree": 3,
"name": "y"
},
{
"id": "P1",
"group": 0,
"degree": 3,
"name": "z"
},
{
"id": "P2",
"group": 0,
"degree": 1,
"name": "w"
}
],
"links": [
{
"source": "P0",
"target": "A0"
},
{
"source": "P1",
"target": "A0"
},
{
"source": "P2",
"target": "A0"
}
]
}
Here is a portion of my code.
var width = 1200,
height = 800,
radius = Math.min(width, height) / 2 - 30;
//console.log(");
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var rd_at = 3,
rd_pp = 2.5;
var author_cord = [];author_cord.push({x:width / 2,y:height / 2});
var given_person = 'x';
d3.json("json_file.json", function(graph) {
var simulation = d3.forceSimulation(graph.nodes)
.force("charge", d3.forceManyBody().strength(-500))
.force("center", d3.forceCenter(width / 2, height / 2))//ATTRACT NODES TO CENTER(width / 2, height / 2)
.force("x", d3.forceX(width / 2).strength(1))//X ALLIGN
.force("y", d3.forceY(height / 2).strength(1))//Y ALLIGN
.force("link", d3.forceLink(graph.links).id(function(d) {return d.id; ).distance(40).strength(1))
.stop();
var loading = svg.append("text")
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.text("Simulating. One moment please…");
d3.timeout(function() {
loading.remove();
for (var i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
simulation.tick();
}
var all_dist = [];
graph.nodes.forEach(function(d){
var d_x = d.x - author_cord[0].x;
var d_y = d.y - author_cord[0].y;
var dist = Math.sqrt(d_x*d_x + d_y+d_y);
all_dist.push(dt);
});
var max_dist = d3.max(all_dist, function(d) {
return d;
});
var r = d3.scaleLinear()
.domain([0,12])
.range([0, max_dist]);
var line = d3.lineRadial()
.radius(function(d) {
return r(d[1]);
});
var gr = svg.append("g")
.attr("class", "r axis")
.selectAll("g")
.data(r.ticks(10).slice(1))
.enter().append("g");
gr.append("circle")
.attr("r", r);
var links = svg.append("g")
.attr("stroke", "grey")
.attr("stroke-width", 1)
.selectAll("line")
.data(graph.links)
.enter().append("line")
.style("opacity", function(d) { return d.target.name == given_author? 0 : 1; } )
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
var n = svg.append("g")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", function(d) {return d.group == 0 ? rd_at : rd_pp;})
.attr("fill", function(d) { return color(d.group); })
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("stroke", "#000")//.attr("stroke", function(d) {return d.group == 0 ? "red": "blue";})
.attr("stroke-width", function(d) {return d.group == 0 ? 1.5 : 1;});
});
});
Here is my output so far. . Here, in the picture green nodes are group 0 node and orange nodes are group 1. Here, center node is the ego node that should be place in the inner most center position of the radial plot
Your svg selection actually corresponds to a group already translated by half width and height:
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
Therefore, you can either change the "center", "x" and "y" in the simulation or, alternatively, you can just remove that group from the svg selection and translating the circles' groups instead:
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var gr = svg.append("g")
.attr("class", "r axis")
.selectAll("g")
.data(r.ticks(10).slice(1))
.enter()
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
I am trying to implement the following example to animate a path using Leaflet and D3.js: http://zevross.com/blog/2014/09/30/use-the-amazing-d3-library-to-animate-a-path-on-a-leaflet-map/.
I receive an error in line 110 saying that d is undefined and I can't find a solution. Any idea on how to solve it?
<!DOCTYPE html5>
<html>
<head>
<meta charset="utf-8" />
<script src="https://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css"
integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet.js"
integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw=="
crossorigin=""></script>
<style>
html,
body {
height: 100%;
width: 100%;
}
body {
margin: 0;
}
#map {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript">
// set up the map
map = new L.Map('map');
// create the tile layer with correct attribution
var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmAttrib='Map data © OpenStreetMap contributors';
var osm = new L.TileLayer(osmUrl, {minZoom: 8, maxZoom: 15, attribution: osmAttrib});
// start the map in Donosti
map.setView(new L.LatLng(40.72332345541449, -73.99),14);
map.addLayer(osm);
var svg = d3.select(map.getPanes().overlayPane).append("svg");
var g = svg.append("g").attr("class", "leaflet-zoom-hide");
d3.json("points.geojson", function(collection) {
var featuresdata = collection.features.filter(function(d) {
return d.properties.id == "route1"
});
var transform = d3.geo.transform({
point: projectPoint
});
var d3path = d3.geo.path().projection(transform);
var toLine = d3.svg.line()
.interpolate("linear")
.x(function(d) {
return applyLatLngToLayer(d).x
})
.y(function(d) {
return applyLatLngToLayer(d).y
});
var ptFeatures = g.selectAll("circle")
.data(featuresdata)
.enter()
.append("circle")
.attr("r", 3)
.attr("class", "waypoints");
var linePath = g.selectAll(".lineConnect")
.data([featuresdata])
.enter()
.append("path")
.attr("class", "lineConnect");
// This will be our traveling circle it will
// travel along our path
var marker = g.append("circle")
.attr("r", 10)
.attr("id", "marker")
.attr("class", "travelMarker");
var originANDdestination = [featuresdata[0], featuresdata[17]];
var begend = g.selectAll(".drinks")
.data(originANDdestination)
.enter()
.append("circle", ".drinks")
.attr("r", 5)
.style("fill", "red")
.style("opacity", "1");
// I want names for my coffee and beer
var text = g.selectAll("text")
.data(originANDdestination)
.enter()
.append("text")
.text(function(d) {
return d.properties.name
})
.attr("class", "locnames")
.attr("y", function(d) {
return -10
});
// when the user zooms in or out you need to reset
// the view
map.on("viewreset", reset);
// this puts stuff on the map!
reset();
transition();
// Reposition the SVG to cover the features.
function reset() {
var bounds = d3path.bounds(collection),
topLeft = bounds[0],
bottomRight = bounds[1];
text.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
});
// for the points we need to convert from latlong
// to map units
begend.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
});
ptFeatures.attr("transform",
function(d) {
return "translate(" +
applyLatLngToLayer(d).x + "," +
applyLatLngToLayer(d).y + ")";
});
// again, not best practice, but I'm harding coding
// the starting point
marker.attr("transform",
function() {
var y = featuresdata[0].geometry.coordinates[1]
var x = featuresdata[0].geometry.coordinates[0]
return "translate(" +
map.latLngToLayerPoint(new L.LatLng(y, x)).x + "," +
map.latLngToLayerPoint(new L.LatLng(y, x)).y + ")";
});
// Setting the size and location of the overall SVG container
svg.attr("width", bottomRight[0] - topLeft[0] + 120)
.attr("height", bottomRight[1] - topLeft[1] + 120)
.style("left", topLeft[0] - 50 + "px")
.style("top", topLeft[1] - 50 + "px");
// linePath.attr("d", d3path);
linePath.attr("d", toLine)
// ptPath.attr("d", d3path);
g.attr("transform", "translate(" + (-topLeft[0] + 50) + "," + (-topLeft[1] + 50) + ")");
}; // end reset
function transition() {
linePath.transition()
.duration(7500)
.attrTween("stroke-dasharray", tweenDash)
.each("end", function() {
d3.select(this).call(transition);// infinite loop
});
}; //end transition
// this function feeds the attrTween operator above with the
// stroke and dash lengths
function tweenDash() {
return function(t) {
//total length of path (single value)
var l = linePath.node().getTotalLength();
interpolate = d3.interpolateString("0," + l, l + "," + l);
//t is fraction of time 0-1 since transition began
var marker = d3.select("#marker");
// p is the point on the line (coordinates) at a given length
// along the line. In this case if l=50 and we're midway through
// the time then this would 25.
var p = linePath.node().getPointAtLength(t * l);
//Move the marker to that point
marker.attr("transform", "translate(" + p.x + "," + p.y + ")"); //move marker
console.log(interpolate(t))
return interpolate(t);
}
}; //end tweenDash
function projectPoint(x, y) {
var point = map.latLngToLayerPoint(new L.LatLng(y, x));
this.stream.point(point.x, point.y);
}; //end projectPoint
});
function applyLatLngToLayer(d) {
var y = d.geometry.coordinates[1]
var x = d.geometry.coordinates[0]
return map.latLngToLayerPoint(new L.LatLng(y, x))
};
</script>
</body>
</html>
And the external file needed to run the code is:
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature",
"properties": { "latitude": 40.722390, "longitude": -73.995170, "time": 1, "id": "route1", "name":"Gimme" },
"geometry": { "type": "Point", "coordinates": [ -73.99517, 40.72239 ] } },
{ "type": "Feature",
"properties": { "latitude": 40.721580, "longitude": -73.995480, "time": 2, "id": "route1", "name":"Along route" },
"geometry": { "type": "Point", "coordinates": [ -73.99548, 40.72158 ] } }]}
I am trying one of Mike Bostock's collapsible tree examples with d3 v3. However, I always receive the following error:
TypeError: root_03.children is undefined
I have referred to Stack Overflow for troubleshooting but the solutions do not work.
Does anyone have the answer to this? Or could it be because this code does not work at v3 anymore?
Here is my JS code:
var w_canvas_03 = 960;
var h_canvas_03 = 800;
var margin_03 = {
top: 50,
right: 20,
bottom: 30,
left: 20
};
var w_chart_03 = w_canvas_03 - margin_03.left - margin_03.right;
var h_chart_03 = h_canvas_03 - margin_03.top - margin_03.bottom;
var i_03 = 0;
var duration_03 = 750;
var root_03;
var tree_03 = d3.layout.tree()
.size([h_chart_03, w_chart_03]);
var diagonal_03 = d3.svg.diagonal()
.projection(function(data_){
return [data_.y, data_.x];
});
var svg_03 = d3.select("body")
.append("svg")
.attr("width", w_canvas_03)
.attr("height", h_canvas_03)
.append("g")
.attr("transform", "translate(" + margin_03.left + "," + margin_03.top + ")");
d3.json("resource/json_remark.json", function(error_, source_){
if (error_) throw error_;
root_03 = source_;
root_03.x0 = h_chart_03 / 2;
root_03.y0 = 0;
console.log(root_03)
function Collapse_03(data_){
if (data_.children){
data_._children = data_.children;
data_._children.forEach(Collapse_03);
data_.children = null;
}
}
root_03.children.forEach(Collapse_03);
Update_03(root_03);
})
d3.select(self.frameElement).style("height", h_canvas_03);
function Update_03(source_){
// Computing the flattened node list
var nodeAll_03 = tree_03.nodes(root_03).reverse()
var linkAll_03 = tree_03.links(nodeAll_03);
// Normalizing for fixed-depth
nodeAll_03.forEach(function(data_){
data_.y = 180 * data_.depth;
});
// Updating the node
var node_03 = svg_03.selectAll("g.node")
.data(nodeAll_03, function(data_){
return data_.id || (data_.id = ++i_03);
});
var nodeEnter_03 = node_03.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(data_){
return "translate(" + source_.y0 + "," + source_.x0 + ")";
})
.on("click", Click_03);
// Entering any new nodes at the parent's previous position
nodeEnter_03.append("circle")
.attr("r", 1e-6)
.style("fill", function(data_){
data_._children ? "lightsteelblue" : "#fff"
; });
nodeEnter_03.append("text")
.attr("x", function(data_){
data_.children || data_.children ? -10:10;
})
.attr("dy", "0.35em")
.attr("text-anchor", function(data_){
return data_.children || data_.children ? "end" : "start";
})
.text(function(data_){
return data_.name;
})
.style("fill-opacity", 1e-6);
// Transitioning nodes to their new position
var nodeUpdate_03 = node_03.transition()
.duration(duration_03)
.attr("transform", function(data_){
return "translate(" + data_.y + "," + data_.x + ")";
});
nodeUpdate_03.select("circle")
.attr("r", 4.5)
.style("fill", function(data_){
return data_._children ? "lightsteelblue" : "#fff;"
});
nodeUpdate_03.select("text")
.style("fill-opacity", 1);
// Transitioning exiting nodes to the parent's new position
var nodeExit_03 = node_03.exit()
.transition()
.duration(duration_03)
.attr("transform", function(data_){
return "translate(" + source_.y + "," + source_.x + ")";
})
.remove();
nodeExit_03.select("circle")
.attr("r", 1e-6);
nodeExit_03.select("text")
.style("fill-opacity", 1e-6);
// Updating the links
var link_03 = svg_03.selectAll("path.link")
.data(linkAll_03, function(data_){
return data_.target.id;
});
// Entering any new links at the parent's previous position
link_03.enter()
.insert("path", "g")
.attr("class", "link")
.attr("d", function(data_){
var o_03 = {x: source_.x0, y: source_.y0};
return diagonal_03({source: o_03, target: o_03});
});
// Transitioning links to their new position
link_03.transition()
.duration(duration_03)
.attr("d", diagonal_03);
// Transitioning exiting nodes to the parent's new position
link_03.exit()
.transition()
.duration(duration_03)
.attr("d", function(data_){
var o_03 = {x: source_.x, y: source_.y};
return diagonal_03({source: o_03, target: o_03});
})
.remove();
// Stashing the old positions for transition
nodeAll_03.forEach(function(data_){
data_.x0 = data_.x;
data_.y0 = data_.y;
});
}
// Toggling children on click
function Click_03(data_){
if (data_.children){
data_._children = data_.children;
data_.children = null;
} else{
data_.children = data_._children;
data_._children = null;
}
Update_03(data_)
}
And here is the simplified version of my JSON file:
[
{
"name": "Neutral",
"children": [
{
"name": "Fruit",
"children": [
{
"name": "Apple"
},
{
"name": "Orange"
}
]
}
]
}
]
If you look at the original Bostock's bl.ocks you'll see that its JSON ("flare.json") file has an object, not an array. However, your JSON file has an array (with a single object inside it).
Therefore, the solution is simple:
root_03 = source_[0];
//1st element-----^
This get's the first element of that array, which is the root object with the children property.
Here is a bl.ocks with your code: https://bl.ocks.org/anonymous/ae2bcac26194865317d0ec6b55361221/070902f5daaf9d90f061455d11d04769439a8b4c
I use d3.tree().nodeSize() to Calculate the coordinates,but I see the cousin's distance is twice that of the brothers.see the Image
I want the distance to be consistent.I did not see how to solve in the api,How to deal with it?
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
g = svg.append("g").attr("transform", "translate(40,200)");
var tree = d3.tree()
.nodeSize([50,50]);//make node space
var data={
id:1,
children:[
{
id:2,
children:[
{
id:3
},
{
id:4
}
]
},
{
id:5,
children:[
{id:6},
{id:7}
]
}
]
};
var root=d3.hierarchy(data)
tree(root)
//console.log(root)
var link = g.selectAll(".link")
.data(root.descendants().slice(1))
.enter().append("path")
.attr("class", "link")
.attr("d", diagonal).style("fill","none").style("stroke-width",1).style("stroke","#000000");
var node = g.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });// add node
node.append("circle")
.attr("r", 2.5);
node.append("text")
.attr("dy", 3)
.attr("x", function(d) { return d.children ? -8 : 8; })
.style("text-anchor", function(d) { return d.children ? "end" : "start"; })
.text(function(d) { return d.id; });
function diagonal(d) {
return "M" + d.y + "," + d.x
+ "L" + d.parent.y + "," + d.parent.x;
}
<svg width="960" height="2400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
recently I see tree.separation to deal this problem
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
g = svg.append("g").attr("transform", "translate(40,200)");
var tree = d3.tree()
.nodeSize([50,50])//make node space
.separation(function(a,b){
return a.parrent==b.parrent?1:1
});// make separation accessor 1
var data={
id:1,
children:[
{
id:2,
children:[
{
id:3
},
{
id:4
}
]
},
{
id:5,
children:[
{id:6},
{id:7}
]
}
]
};
var root=d3.hierarchy(data)
tree(root)
//console.log(root)
var link = g.selectAll(".link")
.data(root.descendants().slice(1))
.enter().append("path")
.attr("class", "link")
.attr("d", diagonal).style("fill","none").style("stroke-width",1).style("stroke","#000000");
var node = g.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });// add node
node.append("circle")
.attr("r", 2.5);
node.append("text")
.attr("dy", 3)
.attr("x", function(d) { return d.children ? -8 : 8; })
.style("text-anchor", function(d) { return d.children ? "end" : "start"; })
.text(function(d) { return d.id; });
function diagonal(d) {
return "M" + d.y + "," + d.x
+ "L" + d.parent.y + "," + d.parent.x;
}
<svg width="960" height="2400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
return a.parrent==b.parrent?1:1
doesn't do anything.
You should use return a.parrent==b.parrent?1:2 or just return 1
I'm trying to create a circle pack graph using nest() and .rollup. I'm getting the following errors:
Error: Invalid value for <g> attribute transform="translate(undefined,undefined)"
Error: Invalid value for <circle> attribute r="NaN"
I want the circles to be sized according to the number of companies in each country. I'm attempting to adapt Mike Bostock's Flare circle-pack example.
If anyone could point me in the direction of any information, I'd be very grateful.
JS code:
var diameter = 960,
format = d3.format(",d");
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) { return d.size; });
var svg = d3.select("body").append("svg")
.attr("width", diameter)
.attr("height", diameter)
.append("g")
.attr("transform", "translate(2,2)");
//Get data
d3.json("data/countriesNested.php", function(error, data){
var submissionsByCountry = d3.nest()
.key(function(d) { return d.Country; })
.key(function(d) { return d.Organisation; })
.rollup(function(leaves) { return leaves.length; })
.entries(data);
var node = svg.datum(data).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.cx + "," + d.cy + ")"; });
node.append("title")
.text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });
node.append("circle")
.attr("r", function(d) { return d.r; });
});
d3.select(self.frameElement).style("height", diameter + "px");
</script>
Data file (from MySQL using PHP script):
[
{
"Country":"USA",
"ID":4,
"Organisation":"Company 1"
},
{
"Country":"USA",
"ID":5,
"Organisation":"Company 2"
},
{
"Country":"USA",
"ID":6,
"Organisation":"Company 3"
},
{
"Country":"FRANCE",
"ID":19,
"Organisation":"Company 4"
},
{
"Country":"FRANCE",
"ID":24,
"Organisation":"Company 5"
},
{
"Country":"GERMANY",
"ID":10,
"Organisation":"Company 6"
},
{
"Country":"ITALY",
"ID":7,
"Organisation":"Company 7"
},
.....
Thanks for reading.
There are a few errors in your code that need to be fixed:
You need to set the accessor functions for children and values on your pack layout:
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.children(function(d) {
return d.values; // accessor for children
})
.value(function(d) {
return d.values; // accessor for values
});
Your d3.nest() returns an array but d3.pack() requires you to supply a root object containing the hierarchy. You have to create a root object and put your nested array inside:
var countryRoot = {
key: "root",
values: submissionsByCountry
};
In your code you nest your data into submissionsByCountry but you are not using this variable anywhere else. So you obviously have to refer to it when binding data to your svg. This is accomplished by the above mentioned root object which is later on bound to the svg.
var node = svg.datum(countryRoot).selectAll(".node")
The attributes the pack layout is adding to your data nodes include values x and y, whereas you refered to them as cx and cy which are attributes to <svg:circle> but are not present in your data. Hence, you got your transform="translate(undefined,undefined)" error messages. You should use these attributes as such:
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
I put together a working plunk.
So, you want a parent circle (let's call it the world), with child circles representing each country sized with a count of entries in your JSON array?
d3.json("data/countriesNested.php", function(error, data) {
var submissionsByCountry = d3.nest()
.key(function(d) {
return d.Country;
})
.rollup(function(leaves) {
return leaves.length;
})
.entries(data);
var root = {
"key": "world",
"children": submissionsByCountry
};
...
This will give you something closely resembling the flare.json.
Next, you need to give d3 the right accessor for your circle size.
var pack = d3.layout.pack()
.size([diameter - 4, diameter - 4])
.value(function(d) {
return d.values; //<-- this comes from your roll-up and is the count.
});
Finally it looks like you changed the example code to access non-exist cx and cy attributes in the resulting nodes data:
var node = svg.datum(root).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) {
return d.children ? "node" : "leaf node";
})
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; //<-- this is .x, .y
});
Here's an example.