d3js v4 sunburst chart - javascript

I am trying to map some data using [d3js zoomable sunburst][1]
[1]: https://bl.ocks.org/mbostock/4348373. Following the example I did the same steps. But I think its not able to read the data correctly . Below is the code which I have so far and since its not able to read the data the output is a black circle.
https://jsfiddle.net/snt1/mbszu1u5/3/
root = d3.hierarchy(root);
root.sum(function(d) { return d.count; });
svg.selectAll("path")
.data(partition(root).descendants())
.enter().append("path")
.attr("d", arc)
.style("fill", function(d) { return color((d.children ? d : d.parent).data.name); })
.on("click", click)
.append("title")
.text(function(d) { return d.data.name + "\n" + formatNumber(d.value); });

Related

Why legend does not work correctly with d3.js

This is my code :
legend = svg.append("g")
.data(json.links)
.attr("class","legend")
.attr("transform","translate(50,30)")
.attr("data-legend", function(d){ return d.relation; })
.style("fill", function (d) { return color(d.group); })
.call(d3.legend);
It's work but only one relation appears in the lengend.
Can you help me ?
Thanks a lot !

How to properly resize voronoi in a reponsive chart

I have a responsive line chart made with d3, but have problem resizing the voronoi used for hover state. I suspect I don't refer to it the right way...
I added the voronoi here:
var voronoiGroup = svg.append("g")
.attr("class", "voronoi");
voronoiGroup.selectAll("line")
.data(voronoi(d3.nest()
.key(function(d) { return xScale(d.date) + "," + yScale(d.value); })
.rollup(function(v) { return v[0]; })
.entries(d3.merge(ranksFiltered.map(function(d) { return d.values;})))
.map(function(d) { return d.values; })))
.enter()
.append("path")
.attr("id", "cells")
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.datum(function(d) { return d.point; });
and in my resize function, I attempt to redraw it:
svg.select("#cells path")
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.datum(function(d) { return d.point; });;
If someone wants to take a stab at it, there's a plunk here:
http://plnkr.co/edit/Jj4QpF1bqK901WalNMmR
Thanks for you time!
The Voronoi Geom is calculating pixel positions in relation to the clipExtent. Since you are changing your width (the clipextent), you need to rerun the calculations. This is one of the few times with d3 that I'd recommend just remove the paths under your voronoi group and re-adding them:
voronoi.clipExtent([[0, -10], [width+10, height]]);
voronoiGroup.selectAll("path").remove();
voronoiGroup.selectAll("cells")
.data(voronoi(vd))
.enter()
.append("path")
.attr("class", "cells")
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.datum(function(d) { return d.point; })
.attr("stroke", "red")
.on("mouseover", mouseover)
.on("mouseout", mouseout);
Updated plunker.

How to get topojson's geometry by name (properties' value)?

I am a TopoJson newbie and I have some data that looks like this....
{"type":"Polygon","properties":{"name":"Arkansas"},"arcs":[[0,1,2,3,4,5]]}
I am trying to say just output Arkansas so I cam up with the following (I am using underscore.js)...
var collection = topojson.feature(us, us.objects.subunits).features;
var final = [];
_.forEach(collection, function(item){
if(item.properties.name == "Arkansas"){
final.push(item);
}
});
svg.selectAll(".subunit")
.data(final)
.enter()
.append("path")
.attr("class", function(d) { return "subunit " + d.id; })
.attr("d", path);
This works great but isn't there an easier way? Is there something like us.objects.subunits["Arkansas"] I can do?
(From my mobile and memory, try out the following)
Usually, the way to go is something like :
var final = topojson.feature(us, us.objects.subunits).features;
svg.selectAll(".subunit")
.data(final)
.enter()
.append("path")
.attr("class", function(d) { return "subunit " + d.id; })
.attr("d", function(d){ if(d.properties.name == "Arkansas"){ return d } });
The filtering is directly within the .attr('d', function(d){…}). If not working, try .attr('d', function(d, path){…}) and return the path.

Converting only certain nodes in D3 Sankey chart from rectangle to circle

I would like to reproduce the process from D3 Sankey chart using circle node instead of rectangle node, however, I would like to select only certain nodes to change from rectangles to circles.
For example, in this jsfiddle used in the example, how would you only select Node 4 and Node 7 to be converted to a circle?
I updated your fiddle.
Basically you just need some way to select the nodes that you want to make different. I used unique classname so that you can style them with CSS as well. I didn't feel like writing the code to select just 4 and 7 (I'm lazy) so I just selected all of the even nodes instead.
// add in the nodes
var node = svg.append("g").selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", function (d, i) { return i % 2 ? "node rect" : "node circle";
})
Then you can use that to select the nodes and add circles instead of rectangles.
svg.selectAll(".node.circle").append("circle")
.attr("r", sankey.nodeWidth() / 2)
.attr("cy", function(d) { return d.dy/2; })
.attr("cx", sankey.nodeWidth() / 2)
.style("fill", function (d) {
There is also another similar approach, illustrated in the following jsfiddle.
I started from this fiddle (from another SO question that you merntioned)), where all nodes had already been converted to circles:
Then I modified existing and added some new code that involves filtering during creation of circles:
// add the circles for "node4" and "node7"
node
.filter(function(d){ return (d.name == "node4") || (d.name == "node7"); })
.append("circle")
.attr("cx", sankey.nodeWidth()/2)
.attr("cy", function (d) {
return d.dy/2;
})
.attr("r", function (d) {
return Math.sqrt(d.dy);
})
.style("fill", function (d) {
return d.color = color(d.name.replace(/ .*/, ""));
})
.style("fill-opacity", ".9")
.style("shape-rendering", "crispEdges")
.style("stroke", function (d) {
return d3.rgb(d.color).darker(2);
})
.append("title")
.text(function (d) {
return d.name + "\n" + format(d.value);
});
// add the rectangles for the rest of the nodes
node
.filter(function(d){ return !((d.name == "node4") || (d.name == "node7")); })
.append("rect")
.attr("y", function (d) {
return d.dy/2 - Math.sqrt(d.dy)/2;
})
.attr("height", function (d) {
return Math.sqrt(d.dy);
})
.attr("width", sankey.nodeWidth())
.style("fill", function (d) {
return d.color = color(d.name.replace(/ .*/, ""));
})
.style("fill-opacity", ".9")
.style("shape-rendering", "crispEdges")
.style("stroke", function (d) {
return d3.rgb(d.color).darker(2);
})
.append("title")
.text(function (d) {
return d.name + "\n" + format(d.value);
});
Similar code had to be modified for accurate positioning text beside rectangles.
I believe the final result looks natural, even though it lost some of the qualities of the original Sankey (like wider connections).

D3js filter selection

I am creating an interactive bubble chart of fortune 500 data. I am trying to reduce a selection but can't figure out why it's not working as I expect.
var bubble = d3.layout.pack()
...
d3.json("js/data/fortune2009.json", function(json) {
var node = svg.data([json]).selectAll("g.node")
.data(bubble.nodes); // filter here?
node.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("circle")
.attr("r", function(d) { return d.r; })
.attr("class", function(d) { return "q" + color(d.Profit) + "-9"; });
node.filter(function(d) { return !d.children; })
.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.Company.substring(0, d.r / 3); });
});
The JSON data looks like this:
{
"children":[
{
"Year" : "2009",
"Rank" : "1",
"Revenue" : "442",
"Profit" : "851.00",
"Company" : "Exxon Mobil"
},
....
}
I want to remove the parent node. I am trying to use a filter function like described here.
.filter(function(d) { return !d.children; })
But if i add my filter function where I initialize the node selection, either nothing happens or I get an error.
(The filter works when I apply it before appending text)
How do I solve this?
UPDATE: Here is a JSFIDDLE http://jsfiddle.net/B9w4N/8/ showing my problem.
You had the right idea. You just needed to apply the filter where the circles are created (in addition to where the text is created):
node
.filter(function(d) { return !d.children; })
.append("circle")
.attr("r", function(d) { return d.r; });
Forked version on JSFiddle
You can filter the array that the layout outputs:
var node = svg.data([fortune2009]).selectAll("g.node")
.data(function(d) {
return bubble.nodes(d).filter(function(v) {
return v.depth > 0;
});
});
See updated fiddle: http://jsfiddle.net/B9w4N/10/

Categories