4

I'm trying to make a chorolpleth with a rotating globe in d3. I can get the globe to render out fine but I can't get the countries to fill with the proper color scale.

Longer explanation. I basically started with Mike Bostock's code for the spinning globe found here:

http://bl.ocks.org/mbostock/6747043

I've got some economic data for about 85 countries that I'm reading in from an external csv. And I'm trying to get the colors to map to the countries per the values in the csv. There's another Bostock example of a choropleth here (static and just the US and referenced frequently in SO d3 questions):

http://bl.ocks.org/mbostock/4060606

What I end up with are solid white (#fff) countries on the face of the globe. Which is not what I'm trying to get.

I added the ISO 3166-1 numeric codes to my csv so that I could match them to the same ids inside the topojson data. So my csv looks like:

country     id      curracct
Germany     276     260.9
Sweden      752     7.24
Etc.

My first thought was just to create a variable that was a function, which went through the length of the 'countries' from the topojson data and found the countries where the id equaled the id from the csv countries, then assigned the scaled color to them. Then I set 'context.fillStyle' equal to that variable/function. That didn't work.

Then I just put 'context.fillStyle' directly inside of a function (which is the code as it's currently written below). That didn't work either.

Again, I'm trying to get the 85 or so countries with data in the csv to appear color-coded on the front side spinning globe according to the scale I've set up.

My guess is that there is something I don't understand about the variable 'context' and what it's handling. If this were .style("fill", [put my function here to map the colors]) syntax I would be okay. So, anyone got any thoughts?

I'm not a coder. Actually I guess I am as I am trying to write some code. Maybe I should just say I'm a self-taught and mostly terrible coder. Although through examples, the JS console, and other questions on SO, I can usually work out where the errors are. This time I've reached a wall. Any help is appreciated. Thanks.

var width = 560,
    height = 560,
    speed = -1e-2,
    start = Date.now();

var sphere = {type: "Sphere"};

var color = d3.scale.quantize()
    .range(["#ffffd9", "#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"]);

var projection = d3.geo.orthographic()
    .scale(width / 2.1)
    .clipAngle(90)
    .translate([width / 2, height / 2]);

var graticule = d3.geo.graticule();

var canvas = d3.select("body")
    .append("canvas")
    .attr("width", width)
    .attr("height", height);

var context = canvas.node().getContext("2d");

var path = d3.geo.path()
    .projection(projection)
    .context(context);

queue()
    .defer(d3.json, "/d3/world-110m.json")
    .defer(d3.csv, "trade.csv")
    .await(globeTrade);

function globeTrade(error, topo, data) {
      var land = topojson.feature(topo, topo.objects.land),
          countries = topojson.feature(topo, topo.objects.countries),
          borders = topojson.mesh(topo, topo.objects.countries, function(a, b) { return a !== b; }),
    grid = graticule();

    color.domain([0, d3.max(data, function(d){return d.curracct})]);


    d3.timer(function() {
     var λ = speed * (Date.now() - start),
     φ = -15;


    context.clearRect(0, 10, width, height);

    context.beginPath();
    path(sphere);
    context.lineWidth = 2.5;
    context.strokeStyle = "#000";
    context.stroke();
    context.fillStyle = "#fff";
    context.fill();

    context.save();
    context.translate(width / 2, 0);
    context.scale(-1, 1);
    context.translate(-width / 2, 0);
    projection.rotate([λ + 180, -φ]);

    context.beginPath();
    path(land);
    context.fillStyle = "#ddd" //changed to a nuetral gray
    context.fill();

    context.beginPath();
    path(grid);
    context.lineWidth = .5;
    context.strokeStyle = "rgba(119,119,119,.5)";
    context.stroke();

    context.beginPath();
    path(borders);
    context.lineWidth = .25;
    context.strokeStyle="#fff";
    context.stroke();


    context.restore();
    projection.rotate([λ, φ]);

    context.beginPath();
    path(grid);
    context.lineWidth = .5;
    context.strokeStyle = "rgba(119,119,119,.5)";
    context.stroke();

    // This is where I am failing
    context.beginPath();
    path(countries);
    function render (d){
        for (var j = 0; j < countries.features.length; j++) {
            if (d.id == countries.features[j].id) {
                context.fillStyle = color(d.curracct)
                }
            else {
                context.fillStyle = "#737368"; //left Bostock's color for now
            }

        }

    }   
    context.fill();
    context.lineWidth = .1;
    context.strokeStyle = "#000"; 
    context.stroke();       
});

data.forEach(function(d, i) {
    d.curracct = +d.curracct;
    d.id = +d.id;
  });

d3.select(self.frameElement).style("height", height + "px");

    </script>
</body>

noLongerRandom
  • 521
  • 1
  • 5
  • 17

0 Answers0