使用SVG滤镜dropshadow创建响应式D3贴图

时间:2018-08-16 18:27:40

标签: javascript d3.js svg svg-filters

我对D3地图非常陌生,我一直在尝试使用svg滤镜创建具有阴影效果的自适应D3地图。

示例代码由Mike Bostock(drop shadow)和Darren Jaworski(responsive projection)的代码块改编而成。您可以在Codepen上查看示例代码。以下是我的JS代码:

var width = parseInt(d3.select('#mapContainer').style('width'))
  ,height = width/960*600;

var svg = d3.select("svg")
  .attr("width", width)
  .attr("height",height);

var defs = svg.select("defs");


d3.json("https://d3js.org/us-10m.v1.json", function(error, us) {
  if (error) throw error;
  var path = d3.geoPath();

  var projection = d3.geoIdentity()
  .scale(width)
  .translate([width / 2, height / 2])
  .fitSize([width, height],topojson.feature(us, us.objects.states));

  defs.append("path")
      .attr("id", "nation")
      .attr("d", path(topojson.feature(us, us.objects.nation)));

  svg.append("use")
      .attr("xlink:href", "#nation")
      .attr("fill-opacity", 0.2)
      .attr("filter", "url(#blur)");

  svg.append("use")
      .attr("xlink:href", "#nation")
      .attr("fill", "#fff");

  svg.append("path")
      .attr("fill", "none")
      .attr("stroke", "#777")
      .attr("stroke-width", 0.70)
      .attr("d", path(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; })));

 // resize event
 d3.select(window)
            .on("resize", resize);


 // function to resize map 
  function resize() {
      // adjust things when the window size changes
      width = parseInt(d3.select('#mapContainer').style('width'));
      //console.log(parseInt(d3.select('#mapContainer').style('width')));
      height = width/960*600;
      svg.attr('width', width).attr('height', height);
      // update projection
      projection
          .scale(width)
          .translate([width / 2, height / 2])
          .fitSize([width, height],topojson.feature(us, us.objects.states));

      // resize the map
      svg.selectAll('path').attr('d', path);
      svg.select('.land').attr('d', path);
      svg.select('.state').attr('d', path);
  }
});

在示例中,调整大小功能似乎不起作用。在调整窗口大小时,地图将消失,附加在其上的svg过滤器也将消失。

有人可以启发我解决问题吗?如果有人可以提供修复程序?

非常感谢您的帮助!


我用@ rioV8的很好的答案更新了codepen on Responsive US D3 Map with Drop Shadow

1 个答案:

答案 0 :(得分:1)

  • 您是否曾经考虑过连接投影仪和路径生成器?

    var path = d3.geoPath(projection);
    
  • 还可以在resize方法中设置路径。标记2个路径元素

    svg.select('#nation').attr('d', path(topojson.feature(us, us.objects.nation)));
    svg.select('#nation2').attr('d', path(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; })));
    
  • 体内的负担一定要去

     <body>
    
  • 没有类别为landstate的标签

    //svg.select('.land').attr('d', path);
    //svg.select('.state').attr('d', path);
    
  • 为什么调用投影sizetranslate,如果您调用fitSize

这是脚本代码

var width = parseInt(d3.select('#mapContainer').style('width')) - 50
  ,height = width/960*600;

var svg = d3.select("svg")
  .attr("width", width + 50)
  .attr("height",height);

var defs = svg.select("defs");

d3.json("https://d3js.org/us-10m.v1.json", function(error, us) {
  if (error) throw error;

  var topoFeatureStates = topojson.feature(us, us.objects.states);
  var projection = d3.geoIdentity()
      .fitSize([width, height], topoFeatureStates);

  var path = d3.geoPath(projection);

  defs.append("path")
      .datum(topojson.feature(us, us.objects.nation))
      .attr("id", "nation")
      .attr("d", path);

  svg.append("use")
      .attr("xlink:href", "#nation")
      .attr("fill-opacity", 0.2)
      .attr("filter", "url(#blur)");

  svg.append("use")
      .attr("xlink:href", "#nation")
      .attr("fill", "#fff");

  svg.append("path")
      .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
      .attr("fill", "none")
      .attr("stroke", "#777")
      .attr("stroke-width", 0.70)
      .attr("d", path);


 // function to resize map 
  function resize() {
      // adjust things when the window size changes
      width = parseInt(d3.select('#mapContainer').style('width')) - 50;
      //console.log(parseInt(d3.select('#mapContainer').style('width')));
      height = width/960*600;
      svg.attr('width', width + 50).attr('height', height);
      // update projection
      projection
          .fitSize([width, height], topoFeatureStates);

      // resize the map
      svg.selectAll('path').attr('d', path);
  }

  // resize event
  d3.select(window).on("resize", resize);
});

修改

想知道为什么调整大小后的path不起作用,请再看一下响应示例。它将topojson的结果作为基准附加到path

修改了代码以进行相同的操作。