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.
Related
I'm using this link to learn D3.Js
I want to draw circles, but I want a circle for every three months
I tried to create a new data sub of the original data, but this didn't work
https://d3-graph-gallery.com/graph/area_lineDot.html
temp =[]
for (i=0; i< data.length; i=i+3) {
temp.push(data[i]);
}
I need to modify this code
svg.selectAll("myCircles")
.data(data)
.enter()
.append("circle")
.attr("fill", "red")
.attr("stroke", "none")
.attr("cx", function(d) { return x(d.date) })
.attr("cy", function(d) { return y(d.value) })
.attr("r", 3)
Try this:
svg.selectAll("myCircles")
.data(temp) // <---------- Use 'temp' instead of 'data'
.enter()
.append("circle")
.attr("fill", "red")
.attr("stroke", "none")
.attr("cx", function(d) { return x(d.date) })
.attr("cy", function(d) { return y(d.value) })
.attr("r", 3)
I got this working now the issue was the way I was reading the d.date and d.value the data has string need to be change to int
thank you Simon
I'm visualising voyages on a map with D3.js' path. My data is in a JSON file like the following format:
[{"begin_date":1519,"trips":[[-13.821772,14.294839],[-9.517688,-7.958521],[0.598434,-34.704567],[18.374673,-86.850335]]},
{"begin_date":1549,"trips":[[12.821772,-16.294839],[5.517688,-20.958521],[13.598434,-54.704567],[18.374673,-86.850335]]},
{"begin_date":1549,"trips":[[12.821772,-16.294839],[5.517688,-20.958521],[13.598434,-54.704567],[18.374673,-86.850335]]}]
As can be seen, sometimes there are multiple voyages for a year. The following recursive function works:
d3.json("data/output.json", function(error, trips) {
if (error) throw error
var nest = d3.nest()
.key(function(d){
return d.begin_date;
})
.entries(trips)
var trip = svg.selectAll(".voyage");
// Add the year label; the value is set on transition.
var label = svg.append("text")
.attr("class", "year label")
.attr("text-anchor", "end")
.attr("y", height - 400)
.attr("x", width+150)
.text(function(d) {return d});
var pnt = 0;
doTransition();
function doTransition() {
trip.data(nest[pnt].values).enter()
.append("path")
.attr("class", "voyage")
.style("stroke", colorTrips)
.attr('d', function(d) {label.text(d.begin_date); return lineGen(d.trips.map(reversed).map(projection))})
.call(function transition(path) {
path.transition()
.duration(500)
.attrTween("stroke-dasharray", tweenDash)
.each("end", function(d) {
d3.selectAll(".voyage")
.remove()
pnt++;
if (pnt >= nest.length){return;}
doTransition();
})
})
}
Some voyages plot as they should
However some of them, are never plotted (I can see in the log) and it jumps from year 1545-1569 despite there being data points in between. I suspect it is due to the recursive function calling itself before the transition is finished. But I am also not sure, in the slightest.
Hope it is sufficient, I am new to D3.js, and suddenly found myself out of depth.
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); });
I have looked for possible solutions but nothing worked for me.
Problem is when I try to update the data and the pie chart accordingly, the transition does not work and prints error, mentioned in the topic, more than once. I am kinda new to JS, so I am looking for some help.
Code:
var pie = d3.pie();
var pathArc = d3.arc()
.innerRadius(200)
.outerRadius(250);
var color = d3.scaleOrdinal(d3.schemeCategory10);
var t = d3.transition()
.duration(500);
var path = piesvg.selectAll("path")
.data(pie(gdp_values));
path.exit()
.transition(t)
.remove();
path.transition(t)
.attr("d",function (d) {
return pathArc(d);
})
.attr("fill",function(d, i){return color(i);});
path.enter()
.append("path")
.transition(t)
.attr("d",pathArc)
.attr("fill",function(d, i){return color(i);});
Initial dataset(gdp_values);
[407500000000, 417300000000, 439800000000, 680900000000, 980900000000, 1160000000000, 1727000000000, 2249000000000, 2389000000000, 3074000000000]
It does work when data changed to the another similar data, however when changes to the data as follows, transitions doesnot work and throws the same error 40 times.
[7714000000, 123900000000, 846200000000]
Any thoughts?
You have to invert the order of your selections: the enter selection should come before the update selection:
path.enter()
.append("path")
.transition(t)
.attr("d", pathArc)
.attr("fill", function(d, i) {
return color(i);
});
path.transition(t)
.attr("d", function(d) {
return pathArc(d);
})
.attr("fill", function(d, i) {
return color(i);
});
Here is the demo:
var piesvg = d3.select("svg").append("g").attr("transform", "translate(250,250)")
var gdp_values = [407500000000, 417300000000, 439800000000, 680900000000, 980900000000, 1160000000000, 1727000000000, 2249000000000, 2389000000000, 3074000000000];
var gdp_values2 = [7714000000, 123900000000, 846200000000];
var pie = d3.pie();
var pathArc = d3.arc()
.innerRadius(200)
.outerRadius(250);
var color = d3.scaleOrdinal(d3.schemeCategory10);
var t = d3.transition()
.duration(500);
update(gdp_values)
setTimeout(function() {
update(gdp_values2);
}, 1000)
function update(data) {
var path = piesvg.selectAll("path")
.data(pie(data));
path.exit()
.transition(t)
.remove();
path.enter()
.append("path")
.transition(t)
.attr("d", pathArc)
.attr("fill", function(d, i) {
return color(i);
});
path.transition(t)
.attr("d", function(d) {
return pathArc(d);
})
.attr("fill", function(d, i) {
return color(i);
});
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="500"></svg>
I got this error when making data updates to a chart. Solution in my case was to prevent drawing of the chart during the time the data was loading. Guessing the arcTween code doesn't handle data changes gracefully.
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).