简体   繁体   中英

d3 graticule with fill color?

I am trying to display a grid on a world map where each grid cell is filled with a color based on some data (eg, temperature or humidity). I am trying to adapt the simple world map example here: http://techslides.com/demos/d3/d3-worldmap-boilerplate.html

I thought I might be able to use the built-in d3 graticule and add a fill color, like this:

g.append("path")
 .datum(graticule)
 .attr("class", "graticule")
 .attr("d", path)
 .style("fill", function(d, i) { return color(Math.floor((Math.random() * 20) + 1)); });

That doesn't work, though. Is there a way to fill in the grid cells generated by graticule? If not, what's the best way to go about overlaying a lat,long grid on the map with filled cells?

To do something like this, first create data set with all the N/S/E/W to define the limits.

var data set = [{W: -5.0, N: 50.0, E: 10.0, S: 40.0 }, {W: -95.0, N: 50.0, E: -40.0, S: 40.0 }];

Next post you load your world JSON add the path like this.

d3.json("http://techslides.com/demos/d3/data/world-topo.json", function(error, world) {

  var countries = topojson.feature(world, world.objects.countries).features;

  topo = countries;
  draw(topo);
  //iterate over the dataset created above for making paths.
  dataset.forEach(function(bb){
    var arc = d3.geo.graticule()
      .majorExtent([[bb.W, bb.S], [bb.E, bb.N]])
    //this will append the path to the g group so that it moves accordingly on translate/zoom   
    g.append("path")
        .attr("class", "arc")
        .attr("d", path(arc.outline()));

  });  
});

On Css add:

.arc {
  fill: red;[![enter image description here][1]][1]
  fill-opacity: 0.3;
  stroke: black;
  stroke-opacity: 0.5;
}

Full JS here:

d3.select(window).on("resize", throttle);

var zoom = d3.behavior.zoom()
    .scaleExtent([1, 8])
    .on("zoom", move);

var width = document.getElementById('container').offsetWidth-60;
var height = width / 2;
var dataset = [{W: -5.0, N: 50.0, E: 10.0, S: 40.0 }, {W: -95.0, N: 50.0, E: -40.0, S: 40.0 }];
var topo,projection,path,svg,g;

var tooltip = d3.select("#container").append("div").attr("class", "tooltip hidden");

setup(width,height);

function setup(width,height){
  projection = d3.geo.mercator()
    .translate([0, 0])
    .scale(width / 2 / Math.PI);

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

  svg = d3.select("#container").append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g")
      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
      .call(zoom);
  g = svg.append("g");


}

d3.json("http://techslides.com/demos/d3/data/world-topo.json", function(error, world) {

  var countries = topojson.feature(world, world.objects.countries).features;

  topo = countries;
  draw(topo);
  dataset.forEach(function(bb){
    var arc = d3.geo.graticule()
      .majorExtent([[bb.W, bb.S], [bb.E, bb.N]])

    g.append("path")
        .attr("class", "arc")
        .attr("d", path(arc.outline()));

  });  
});

function draw(topo) {

  var country = g.selectAll(".country").data(topo);

  country.enter().insert("path")
      .attr("class", "country")
      .attr("d", path)
      .attr("id", function(d,i) { return d.id; })
      .attr("title", function(d,i) { return d.properties.name; })
      .style("fill", function(d, i) { return d.properties.color; });

  //ofsets plus width/height of transform, plsu 20 px of padding, plus 20 extra for tooltip offset off mouse
  var offsetL = document.getElementById('container').offsetLeft+(width/2)+40;
  var offsetT =document.getElementById('container').offsetTop+(height/2)+20;

  //tooltips
  country
    .on("mousemove", function(d,i) {
      var mouse = d3.mouse(svg.node()).map( function(d) { return parseInt(d); } );
        tooltip
          .classed("hidden", false)
          .attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px")
          .html(d.properties.name)
      })
      .on("mouseout",  function(d,i) {
        tooltip.classed("hidden", true)
      }); 

}

function redraw() {
  width = document.getElementById('container').offsetWidth-60;
  height = width / 2;
  d3.select('svg').remove();
  setup(width,height);
  draw(topo);
}

function move() {

  var t = d3.event.translate;
  var s = d3.event.scale;  
  var h = height / 3;

  t[0] = Math.min(width / 2 * (s - 1), Math.max(width / 2 * (1 - s), t[0]));
  t[1] = Math.min(height / 2 * (s - 1) + h * s, Math.max(height / 2 * (1 - s) - h * s, t[1]));

  zoom.translate(t);
  g.style("stroke-width", 1 / s).attr("transform", "translate(" + t + ")scale(" + s + ")");

}

var throttleTimer;
function throttle() {
  window.clearTimeout(throttleTimer);
    throttleTimer = window.setTimeout(function() {
      redraw();
    }, 200);
}

Image:

图片

I created d3-grid-map to solve a specific problem of placing sparse global 0.5 degree grid cells on a d3 map by drawing on canvas layers. It should support other grid sizes with some effort. It handles a couple of forms of javascript typed array inputs, but it could use more generalization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM