d3.geo.circle angle does not work? - d3.js

So, I've tried following Jason Davies' answer to the Circle clip and projection with D3 orthographic thread...
I've tried 3 different possibilities :
svg.append("g").attr("class","points")
.selectAll("path")
.data(places.features)
.enter()
.append("path")
//THIS COMMENTED PART DOES NOT WORK
//though the console spits out an array
/*.datum(function(d){
console.log(d.geometry.coordinates)
return d3.geo.circle()
.origin(d.geometry.coordinates)
.angle(2)
})*/
//THIS UNCOMMENTED PART WORKS
//and places the circles accordingly with a fixed size radius
.datum(d3.geo.circle()
.origin(function(d){return d.geometry.coordinates})
.angle(2)
)
//THIS COMMENTED PART DOES NOT WORK
//which is a shame, as my goal is to change the angle of each circle
/*.datum(d3.geo.circle()
.origin(function(d){return d.geometry.coordinates})
.angle(function(d){return 2})
)*/
.attr("class", "point")
.attr("d", path)
How do I get the last commented part to work so that I can change the radius of my circles? Thanx a lot.

After updating to d3 version "5.7.0" I had same issue.
Fixed by using geoCircle.center(center).radius(angle) instead of geo.circle().angle(angle).
Here you can find how it could work.

Related

D3 Force Nodes Clustering at Top Left

https://jsfiddle.net/abalasky/b28mxfL6/7/
function update() {
//Add Nodes
simulation.nodes(graph.nodes)
updateNodes();
simulation.on("tick", ticked);
//Add links
simulation.force('link').links(graph.links)
updateLinks();
}
Link to fiddle above. Was following along with this great D3 guide https://tomroth.com.au/fdg-minimal/. Was able to have my force graph up quickly but now that i am trying to repackage everything in functions all my nodes are clustering at the top. I've tried to move around where i call .on('tick') but have been banging my head against the wall with this for hours. Any guidance would beg greatly appreciated.
The problem is in the definition of node and link variables:
In the original code, these contain the enter selection, e.g.
//draw circles for the nodes
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(nodes_data)
.enter()
.append("circle")
.attr("r", 5)
.attr("fill", "red");
In the jsfiddle code, the selection itself is assigned to the variable:
node = nodesG.selectAll("circle.node")
.data(graph.nodes)
This causes tick not to have anything on what to iterate.
Here is a corrected version of the jsfiddle: https://jsfiddle.net/cb9t7fjo/
how to identify the cause of this type of problems
console.log is your friend in situations like this:
console.log('tick', node) inside the tick function shows that the tick function is executed as expected.
console.log(d.x) inside node.attr('x') shows you that this is never executed.
This helps identify that the problem is with node (and respectively link) variables.

How to switch from d3.svg.line to a choice that allows different coloured segments?

Is there an easy way to draw the line chart, using d3.svg.line, such that you can specify the colour of each segment individually? Or a slot-in replacement for d3.svg.line that allows this kind of control?
My start point was basically this example:
https://gist.github.com/mbostock/1642874
I tried this first:
var line = d3.svg.line()
.x(function(d, i) { return x(i); })
.y(function(d, i) { return y(d.v); })
.style("stroke",function(d){return d>0?"#f00":#0f0";})
;
But it got a function not found complaint.
Then I tried:
var path = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.data([data])
.attr("class", "line")
.style('stroke',function(d,i){return (d>0?'#f00':'#0f0');})
.attr("d", line)
;
But that just gave me all green lines (It turns out d is not my data).
This is a similar question from a couple of years ago, which says "not now, maybe soon". I tried looking at the cool examples like this and this but cannot work out how to relate their code to the code I have.
The short answer is no, there is no drop-in replacement. You have two options for making lines with different coloured segments.
Create the line segments separately.
Use a gradient fill with hard stops to create the illusion of different segments.
For the former, there's a very nice answer to this question that gives more details. The latter way I've used in this visualisation.

Using D3, how can I transition a line one point at time?

I'm working on a visualization project in which one component is a line chart overlayed on a bar graph. I delayed the bar transitions at a time. I would like the line to transition similarly so each point on the line remains "attached" to the bar.
Here's the code for the line:
var line = d3.svg.line()
.x(function(d, i) {
return xScale(i) + 20;
})
.y(function(d) {
return h - yScale(parseFloat(d.performance));
});
svg1.append("svg:path").attr("d", line(dataset[0].months));
And here's where I transition it:
svg1.select("path")
.transition()
.ease("linear")
.duration(1000)
.attr("d", line(dataset[count].months));
I've seen other questions addressing d3 line transitions but none that seem to address my issue, so I hope I'm not a repeater. Thanks in advance!
Note: I did try putting the delay() function in after transition which didn't work. I'm assuming this is because the line is a single <path> instead of multiple <rect> elements...
So this fell off my radar for a while, but I had some time the other day and figured out one approach for doing the delayed transition...
Here is the pen I wrote. I generated some random data and created a simple line chart to showing stock prices to play around with. The trick here is instead of iterating through a selection of elements using transition, we iterate through the dataset updating it point by point and transitioning the line as we go:
dataset.forEach(function(item, index) {
let set = dataset.slice();
// Update the current point in the copy
set[index].price = newPrice();
stock_line.transition()
.delay(index * 500)
.attr('d', line_generator(set));
});
Admittedly this is a bit hacky and possibly overkill, you could just update the whole line at once. Also #Lars mentioned the possibility of using the stroke-dashoffset trick to accomplish this as well. I have played around with that method to animate drawing the line but I'm not sure how I'd use it to accomplish the same delayed animation shown in the pen. If there is a less hacky implementation please let me know and I'll update this answer.

Why do GeoJSON features appear like a negative photo of the features themselves?

I have a pretty standard code thats reads a GeoJSON file and renders its features using D3.js. It works fairly well except with this file: https://github.com/regiskuckaertz/d3/blob/master/circonscriptions.json
The file doesn't look weird or anything, in fact you can preview it on GitHub or geojsonlint.com. However, D3 draws paths that look like the features were used as a clipping mask, i.e. all the shapes are negatives of the features themselves. The code is pretty standard though:
var proj = d3.geo.mercator()
.scale(25000)
.center([6.08642578125,49.777716951563754])
.rotate([-.6, -.2, 0]);
var path = d3.geo.path().projection(proj);
function ready(error, luxembourg) {
svg
.selectAll("path")
.data(luxembourg.features)
.enter().append("path")
.attr("d", path)
.attr("class", function(d) { return quantize(rateById.get(d.properties.name)); })
}
You can have a look here: http://jsfiddle.net/QWZXd/
The same code works with another file, which comes from the same source.
For some reason, the points in these polygons are in reverse order - they ought to be clockwise, but are defined as counterclockwise, and d3 follows the right-hand rule for polygon interpretation.
To fix, reverse the points, either in the file or in JS:
luxembourg.features.forEach(function(feature) {
feature.geometry.coordinates[0].reverse();
});
Fixed fiddle: http://jsfiddle.net/nrabinowitz/QWZXd/1/

error computing area of a closed space in a force layout using d3js

I have a graph which I've laid out using force layout. Basically i want to color the area contained within the cycles in the graph. Here's my code.
I was trying to paint the cycles when the force layout stabilized.
force.on("tick",function(){
// ... I update the position of nodes and the links
if(force.alpha() < 0.006){
force.stop();
// I dont know if there's an easier way of doing this
var xnodes = [];
force.nodes().forEach(function(d){
xnodes.push([d.x, d.y]);
});
// I tried creating a path and filling with with green
vis.select("path.area")
.data([xnodes])
.enter().append("path")
.style("fill", "#00ff00")
.attr("class", "area")
.attr("svg:d", d3.svg.area());
}
});
When i run it in chrome, the debugger shows that it does create a path but the area of the path is 0px x 0px. I'm really confused with this. I even tried setting the array manually. I get the same error.
var ynodes = [[352.3554660996234,304.3361316660001],[449.88953454311286,313.14153937680953],
[392.0458559272036,389.6656922220398],[352.3554660996234,304.3361316660001]];
vis.select("path.area")
.data([ynodes])
.enter().append("path")
.style("fill", "#00ff00")
.attr("class", "area")
.attr("svg:d", d3.svg.area());
However when i put this code in a blank html file (after you include the necessary libraries) it works fine. It does draw a path and fills it with green. I'm really confused here. Any help would be much appreciated. Thanks.

Resources