地图中区域的颜色选择不正确

时间:2017-01-03 11:24:36

标签: javascript d3.js svg geospatial

我不明白为什么传奇标签的颜色并不总是与我代码中地图中的颜色相对应:

这是我的代码(即this code的修改)。文件provincias.json可用here

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.nombre{
  stroke: #000;
  stroke-width: 0.5px
}
.graticule {
  fill: none;
  stroke: #777;
  stroke-width: .5px;
  stroke-opacity: .5;
}
.legendLinear
 {
  font-family: "Lato";
  fill:#c2b59b;
}

.legendTitle {
  font-size: 1em;
}
#tooltip {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  margin: 0;
  padding: 10px;
  width: 200px;
  height: 70px;
  color: white;
  font-family: sans-serif;
  font-size: 1.0em;
  font-weight: bold;
  text-align: center;
  background-color: rgba(0, 0, 0, 0.55);
  opacity: 0;
  pointer-events: none;
  border-radius:5px;
  transition: .2s;
}

</style>
<body>
<div id="container">
  <div id="tooltip">
  </div>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.7.0/d3-legend.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-composite-projections/0.3.5/conicConformalSpain-proj.min.js"></script>
<script>

var width = 1000,
    height = 900;

var projection = d3.geo.conicConformalSpain()
var graticule = d3.geo.graticule().step([2, 2]);

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

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


    svg.append("path")
        .datum(graticule)
        .attr("class", "graticule")
        .attr("d", path);

d3.json("provincias.json", function(error, provincias) {
  d3.json("hdi.json", function(error, hdi) {
  var land = topojson.feature(provincias, provincias.objects.provincias);

  var color = d3.scale.linear()
              .domain([0, 10, 1000, 10000, 100000, 300000])
              .range(["#feebe2","#e5d1ff","#ba93ef", "#8D4CE5","#6100E5","#C94D8C"]); //#feebe2

    svg.selectAll(".nombre")
      .data(land.features)
      .enter()
      .append("path")
      .attr("d", path)
      .attr("class","nombre")
      .style("fill",function(d){ return color(hdi[d.properties.nombre]) })
      .on("mouseover", function(d){
        //Show the tooltip
        var x = d3.event.pageX;
        var y = d3.event.pageY - 40;

        d3.select("#tooltip")
          .style("left", x + "px")
          .style("top", y + "px")
          .style("opacity", 1)
          .text(d.properties.nombre + "," + hdi[d.properties.nombre]);
      })
      .on("mouseout", function(){
        //Hide the tooltip
        d3.select("#tooltip")
          .style("opacity", 0);
      });

    svg
      .append("path")
        .style("fill","none")
        .style("stroke","#000")
        .attr("d", projection.getCompositionBorders());

    d3.select("svg").append("g")
      .attr("class", "legendLinear")
      .attr("transform", "translate(100,500)");

    var legendLinear = d3.legend.color()
                .title("...")
                .shapeHeight(20)
                .shapeWidth(90)
                .shapeRadius(10)
                .cells([0, 10, 1000, 10000, 100000, 300000])
                .orient("horizontal")
                .labelFormat(d3.format(".00f"))
                .labelAlign("start")
                .scale(color);

    svg.select(".legendLinear")
      .call(legendLinear);

});
});


</script>

hdi.json的内容如下:

{"Coruña, A":9, "Alicante":158, "Albacete":3,"Almería":0,"Asturias":13,"Álava":12,"Ávila":0,
"Badajoz":10,"Balears, Illes":331,"Barcelona":250000,"Burgos":5,
"Cantabria":12,"Castellón":316,"Ceuta":9,"Ciudad Real":9,"Cádiz":9,"Cuenca":4,
"Córdoba":11,"Cáceres":2,"Girona":21808,"Jaén":0,
"Granada":9,"Huelva":3,"Huesca":74,
"León":5,"Lleida":9672,"Lugo":3,
"Madrid":507,"Murcia":24,"Málaga":25,"Palencia":2,"Pontevedra":6,
"Navarra":23,"Salamanca":6,"Segovia":4,"Sevilla":16,"Soria":2,
"Santa Cruz de Tenerife":16,"Tarragona":22790,
"Teruel":23,"Toledo":4,"Valladolid":44,
"Valencia":423,"Vizcaya":19,"Zamora":0,"Zaragoza":56,"Guipúzcoa":21,
"Guadalajara":5,"Jaen":2,"Rioja, La": 12, "Palmas, Las": 10,"Ourense":2}

特别的问题是,Tarragona的值22790的颜色与Lleida的颜色9672的颜色相同。但是,根据我的代码,22790Tarragona)小于100000且大于10000,因此它应该在#6100E5中着色,但它是在#8D4CE5中着色。 但是,例如,9672Lleida)小于10000,因此它应该在#8D4CE5中着色(并且它以此颜色着色,所以没关系)

enter image description here

2 个答案:

答案 0 :(得分:4)

您不应该使用线性刻度,根据定义,它具有连续范围并将在颜色之间进行插值。你所描述的是threshold scale。它具有映射到域值子集的离散范围。此外,您必须使用域名为N + 1的范围来调用它,因此,这就是您应该遵循的内容:

var color = d3.scale.threshold()
  .domain([10, 1000, 10000, 100000, 30000])
  .range(["#feebe2","#e5d1ff","#ba93ef", "#8D4CE5","#6100E5","#C94D8C"]);

以下是使用阈值比例和d3-legend创建图例的示例。

<!DOCTYPE html>
<html>

<head>
  <script src="http://d3js.org/d3.v3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/1.7.0/d3-legend.min.js"></script>
</head>

<body>
  <svg></svg>
  <script>
    var color = d3.scale.threshold()
      .domain([10, 1000, 10000, 100000, 300000])
      .range(["#feebe2", "#e5d1ff", "#ba93ef", "#8D4CE5", "#6100E5", "#C94D8C"]);

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

    svg.append("g")
      .attr("class", "legendLog")
      .attr("transform", "translate(20,20)");

    var logLegend = d3.legend.color()
      .labels([0, 10, 1000, 10000, 100000, 300000])
      .scale(color);

    svg.select(".legendLog")
      .call(logLegend);
  </script>
</body>

</html>

答案 1 :(得分:1)

实际上它按预期工作。 莱里达和塔拉戈纳的确切颜色是不同的,前者是#8f4fe5,后者是#8741e5。

由于您使用的线性比例,这些颜色计算如下:

((9672-1000)*#8d4ce5 +(10000-9672)*#ba93ef)/(10000-1000)=#8f4fe5

((22790-10000)*#6100e5 +(100000-22790)*#8d4ce5)/(100000-10000)=#8741e5

直观地说,你的问题是9672比1000更接近10000,而22790也更接近10000而不是100000,所以即使其中一个低于10000,另一个低于10000,它们也是更接近它,​​而不是范围的另一端。 正如马克在答案中所说,可能你不想使用连续的线性刻度。