Skip to content

Instantly share code, notes, and snippets.

@rveciana
Last active December 15, 2015 08:48
Show Gist options
  • Save rveciana/5233218 to your computer and use it in GitHub Desktop.
Save rveciana/5233218 to your computer and use it in GitHub Desktop.
Wrong way to transform a D3 projection

Actualization This behaviour has been corrected and now the example is valid, since the points are ordered the same way in both projections.

From the mailing list:

OK, this has been fixed in release 3.1.4, so you'll no longer need the work-around described in my previous email. Enjoy, and thank you for the bug report!

http://bl.ocks.org/mbostock/580de8199ea3b85f822a

Initial message This example shows how a projection change must NOT be done. It works properly when the D3 version is 3.0.8, but from 3.1.0, the change does strange things. Just change the D3 source at line 13 to https://raw.github.com/mbostock/d3/v3.1.2/d3.min.js to see the effects.

I asked the question [at the D3 mailing list] (https://groups.google.com/forum/?fromgroups=#!topic/d3-js/9j37YsWU6bM).

As Mike Bostock answered:

The issue you are seeing is that projections apply adaptive resampling (as of D3 3.0, which was released last December). Therefore the number of control points for the same geometry may differ when different projections are used, and thus you cannot apply naive path interpolation to transition between two projections.

Mike Bostock has a working example, and Jason David [has an other one] (https://www.jasondavies.com/maps/transition/)

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.states {
fill: #ccc;
stroke: #fff;
}
</style>
<body>
<button type="button" id="change">Change</button>
<script src="https://raw.github.com/mbostock/d3/v3.0.8/d3.min.js"></script>
<script src="http://d3js.org/topojson.v0.min.js"></script>
<script>
var width = 960,
height = 500;
var states;
var projection = d3.geo.mercator()
.center([-97,37])
.scale(4000)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("/mbostock/raw/4090846/us.json", function(error, us) {
states = svg.append("path")
.attr("class", "states")
.datum(topojson.object(us, us.objects.states))
.attr("d", path);
});
d3.select("#change").on("click", function() {
projection = d3.geo.albers();
path.projection(projection);
states.transition()
.duration(10000)
.attr("d", path);
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment