【问题标题】:d3 graticule with fill color?带有填充颜色的d3格线?
【发布时间】:2016-01-11 11:44:43
【问题描述】:

我正在尝试在世界地图上显示一个网格,其中每个网格单元都填充有基于某些数据(例如温度或湿度)的颜色。我正在尝试在这里调整简单的世界地图示例:http://techslides.com/demos/d3/d3-worldmap-boilerplate.html

我认为我可以使用内置的 d3 刻度并添加填充颜色,如下所示:

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

不过,这行不通。有没有办法填充格线生成的网格单元?如果没有,在地图上用填充的单元格覆盖经纬度网格的最佳方法是什么?

【问题讨论】:

  • 类似this 的东西来自this 问题。很酷的东西。
  • 马克,我也看到了。我认为,通过那个例子,我必须为每个单元格制作一个单独的刻度。有没有办法在 d3 中简洁地表达?

标签: javascript d3.js colors


【解决方案1】:

要做这样的事情,首先创建包含所有 N/S/E/W 的数据集来定义限制。

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 }];

下一篇你加载你的世界 JSON 添加这样的路径。

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()));

  });  
});

在 Css 上添加:

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

这里有完整的 JS:

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);
}

图片:

【讨论】:

  • 我很想把工作代码放在这里......但是世界 json 太大了,plunk 不允许加载它,所以如果你需要完整的工作代码,我可以分享它在 Dropbox 上。
【解决方案2】:

我创建了d3-grid-map 来解决通过在画布图层上绘制在 d3 地图上放置稀疏全局 0.5 度网格单元的特定问题。它应该通过一些努力来支持其他网格大小。它处理几种形式的 javascript 类型的数组输入,但它可以使用更多的泛化。

【讨论】:

  • 太棒了!谢谢!
  • Word,如果你试一试,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-27
  • 1970-01-01
  • 1970-01-01
  • 2017-01-05
  • 1970-01-01
  • 2016-10-05
  • 2022-01-02
相关资源
最近更新 更多