• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

D3地图:放大到路径组

d3.js 来源:Dave 6次浏览

我是D3的新手。我需要做的事情:D3地图:放大到路径组

  1. 创建一个单一状态的地图。
  2. 必须显示县边界。
  3. 国家地区北,南,东,西&中央必须填充不同的颜色。每个地区都由县组成。
  4. 当用户点击一个区域时,地图必须放大到该区域。

我到目前为止所能达到的效果如下: 我有第一个3的要求。问题是当我点击一个县时,它会放大该县而不是该区域。

我写的代码是从下面的例子基于:

缩放边界框

https://bl.ocks.org/mbostock/4699541

纽约州与县削峰

https://bl.ocks.org/gregdevs/a73f8a16f129757c037e72ecdebdd8f2

的唯一部分我自己创建的代码(以及我认为需要更改的部分)是注册表的颜色离子。这是通过使用如果然后其他语句设置以下类别

.attr('class', function (d) { 
        if (d.id == "51105" || d.id == "51169" || d.id == "51191" || d.id == "51520" || d.id == "51077" || d.id == "51035" || 
         d.id == "51141" || d.id == "51089" || d.id == "51143" || d.id == "51590" || d.id == "51195" || d.id == "51051" || 
         d.id == "51027" || d.id == "51167" || d.id == "51185" || d.id == "51173" || d.id == "51021" || d.id == "51197" || 
         d.id == "51071" || d.id == "51590" || d.id == "51155" || d.id == "51063" || d.id == "51067" || d.id == "51121" || 
         d.id == "51161" || d.id == "51770") { 
         return "WesternRegion"; 
        } 
        else if (d.id == "51083" || d.id == "51117" || d.id == "51025" || d.id == "51081" || d.id == "51037" || d.id == "51011" || 
          d.id == "51590" || d.id == "51029" || d.id == "51049" || d.id == "51145" || d.id == "51041" || d.id == "51111" || 
          d.id == "51147" || d.id == "51183" || d.id == "51181" || d.id == "51007" || d.id == "51135" || d.id == "51053" || 
          d.id == "51149" || d.id == "51087" || d.id == "51760") { 
         return "SouthernRegion"; 
        } 
        else if (d.id == "51175" || d.id == "51800" || d.id == "51550" || d.id == "51810" || d.id == "51710" || d.id == "51093" || 
          d.id == "51001" || d.id == "51131") { 
         return "EasternRegion"; 
        } 
        else if (d.id == "51165" || d.id == "51171" || d.id == "51069" || d.id == "51043" || d.id == "51107" || d.id == "51059" || 
          d.id == "51013" || d.id == "51510" || d.id == "51139" || d.id == "51187" || d.id == "51157" || d.id == "51061" || d.id == "51153") { 
         return "NorthernRegion"; 
        } 
        else return "CentralRegion"; 
       }) 
       ; 

以下是完整的代码。为了使其工作,需要从https://bl.ocks.org/mbostock/raw/4090846/us.json下载us.json并将其复制到名为脚本的文件夹中。

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

    .outline { 
    stroke: #000; 
    stroke-width: 1.5px; 
} 

path { 
    fill: #ccc; 
    stroke: #fff; 
    stroke-width: .5px; 
} 
.background { 
    fill: none; 
    pointer-events: all; 
} 

.feature { 
    fill: #ccc; 
    cursor: pointer; 
} 

.county.active { 
    fill: orange !important; 
} 

.WesternRegion 
{ 
    fill:Green; 
} 

.EasternRegion 
{ 
    fill:Blue; 
} 

.SouthernRegion 
{ 
    fill:#efce43; 
} 
.NorthernRegion 
{ 
    fill:Purple; 
} 

.mesh { 
    fill: none; 
    stroke: #fff; 
    stroke-linecap: round; 
    stroke-linejoin: round; 
} 


</style> 
<body> 
<script src="//d3js.org/d3.v3.min.js"></script> 
<script src="//d3js.org/topojson.v1.min.js"></script> 
<script> 

    var width = 960, 
     height = 500; 
    active = d3.select(null); 

    var projection = d3.geo.albers() 
     .scale(1000) 
     .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); 

    svg.append("rect") 
     .attr("class", "background") 
     .attr("width", width) 
     .attr("height", height) 
     .on("click", reset); 

    var g = svg.append("g") 
     .style("stroke-width", "1.5px"); 

    d3.json("/Scripts/us.json", function (error, us) { 
     if (error) throw error; 

     var states = topojson.feature(us, us.objects.states), 
      state = states.features.filter(function (d) { return d.id === 51; })[0]; 

     projection.scale(1) 
      .translate([0, 0]); 

     var b = path.bounds(state), 
      s = .95/Math.max((b[1][0] - b[0][0])/width, (b[1][1] - b[0][1])/height), 
      t = [(width - s * (b[1][0] + b[0][0]))/2, (height - s * (b[1][1] + b[0][1]))/2]; 

     projection.scale(s) 
      .translate(t); 

     g.selectAll("path") 
      .datum(topojson.mesh(us, us.objects.states, function (a, b) { return a !== b; })) 
      .attr("class", "mesh") 
      .attr("d", path) 
      .on("click", clicked); 

     g.append("path") 
      .datum(state) 
      .attr("class", "outline") 
      .attr("d", path) 
      .attr('id', 'land'); 

     g.append("clipPath") 
      .attr("id", "clip-land") 
      .append("use") 
     .attr("xlink:href", "#land"); 

     g.selectAll("path") 
      .data(topojson.feature(us, us.objects.counties).features) 
      .enter().append("path") 
      .attr("d", path) 
      .attr('countyId', function (d) { 
       return d.id 
       }) 
      .attr("clip-path", "url(#clip-land)") 
      .on("click", clicked) 
      .attr('class', function (d) { 
        if (d.id == "51105" || d.id == "51169" || d.id == "51191" || d.id == "51520" || d.id == "51077" || d.id == "51035" || 
         d.id == "51141" || d.id == "51089" || d.id == "51143" || d.id == "51590" || d.id == "51195" || d.id == "51051" || 
         d.id == "51027" || d.id == "51167" || d.id == "51185" || d.id == "51173" || d.id == "51021" || d.id == "51197" || 
         d.id == "51071" || d.id == "51590" || d.id == "51155" || d.id == "51063" || d.id == "51067" || d.id == "51121" || 
         d.id == "51161" || d.id == "51770") { 
         return "WesternRegion"; 
        } 
        else if (d.id == "51083" || d.id == "51117" || d.id == "51025" || d.id == "51081" || d.id == "51037" || d.id == "51011" || 
          d.id == "51590" || d.id == "51029" || d.id == "51049" || d.id == "51145" || d.id == "51041" || d.id == "51111" || 
          d.id == "51147" || d.id == "51183" || d.id == "51181" || d.id == "51007" || d.id == "51135" || d.id == "51053" || 
          d.id == "51149" || d.id == "51087" || d.id == "51760") { 
         return "SouthernRegion"; 
        } 
        else if (d.id == "51175" || d.id == "51800" || d.id == "51550" || d.id == "51810" || d.id == "51710" || d.id == "51093" || 
          d.id == "51001" || d.id == "51131") { 
         return "EasternRegion"; 
        } 
        else if (d.id == "51165" || d.id == "51171" || d.id == "51069" || d.id == "51043" || d.id == "51107" || d.id == "51059" || 
          d.id == "51013" || d.id == "51510" || d.id == "51139" || d.id == "51187" || d.id == "51157" || d.id == "51061" || d.id == "51153") { 
         return "NorthernRegion"; 
        } 
        else return "CentralRegion"; 
       }) 
       ; 

    }); 

    function clicked(d) { 
     //  debugger; 
     if (d3.select(this).classed("NorthernRegion")) { 
      alert("You selected Northern Region"); 
     } 
     else if (d3.select(this).classed("SouthernRegion")) { 
      alert("You selected Southern Region"); 
     } 
     else if (d3.select(this).classed("EasternRegion")) { 
      alert("You selected Eastern Region"); 
     } 
     else if (d3.select(this).classed("WesternRegion")) { 
      alert("You selected Western Region"); 
     } 
     else if (d3.select(this).classed("CentralRegion")) { 
      alert("You selected Central Region"); 
     } 

     if (active.node() === this) return reset(); 
     active.classed("active", false); 
     active = d3.select(this).classed("active", true); 

     var bounds = path.bounds(d ), 
     dx = bounds[1][0] - bounds[0][0], 
     dy = bounds[1][1] - bounds[0][1], 
     x = (bounds[0][0] + bounds[1][0])/2, 
     y = (bounds[0][1] + bounds[1][1])/2, 
     scale = .9/Math.max(dx/width, dy/height), 
     translate = [width/2 - scale * x, height/2 - scale * y]; 

     g.transition() 
     .duration(750) 
     .style("stroke-width", 1.5/scale + "px") 
     .attr("transform", "translate(" + translate + ")scale(" + scale + ")"); 

    } 

    function reset() { 

     active.classed("active", false); 
     active = d3.select(null); 

     g.transition() 
     .duration(750) 
     .style("stroke-width", "1.5px") 
     .attr("transform", ""); 
    } 
</script> 

下面是地图的样子: enter image description here

的问题是,它放大到县城不在区域: enter image description here

===========解决方案如下:

首先,你不需要那些大牌if...else报表。他们可以非常简单。例如,要获得clicked函数中的类:

var thisClass = d3.select(this).attr("class"); 

回到您的问题。

一种溶液得到的所有路径与类的点击的元素的和推动的阵列内其边界:

var allBounds = []; 

var allPaths = d3.selectAll("path." + thisClass).each(function(d) { 
    allBounds.push(path.bounds(d)) 
}); 

然后计算所有这些边界的角:

var bound0 = d3.min(allBounds, function(d) { 
    return d[0][0] 
}); 
var bound1 = d3.min(allBounds, function(d) { 
    return d[0][1] 
}); 
var bound2 = d3.max(allBounds, function(d) { 
    return d[1][0] 
}); 
var bound3 = d3.max(allBounds, function(d) { 
    return d[1][1] 
}); 

var bounds = path.bounds(d), 
    dx = bound2 - bound0, 
    dy = bound3 - bound1, 
    x = (bound0 + bound2)/2, 
    y = (bound1 + bound3)/2, 
    scale = .9/Math.max(dx/width, dy/height), 
    translate = [width/2 - scale * x, height/2 - scale * y]; 

这里是更新后的bl.ocks:https://bl.ocks.org/anonymous/3e473b01de29cb7a3c0a6d8807b8b247/f6675e001dc7dcdb7ffd4c437944bb3233b417ca

PS:如果你点击中间区域(灰色区域),它将会是工作。原因很简单:在您的代码中,您正在将类centralRegion设置为if...else语句中没有给定ID的所有路径。你必须改变这一点。

PPS:您必须重构代码才能将active类设置为所有县。


版权声明:本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。
喜欢 (0)