D3.js Choropleth使用JSON中的数据

时间:2017-05-27 23:20:25

标签: json d3.js topojson choropleth

我正在尝试制作类似于Mike Bostock&Chorsopleth(https://bl.ocks.org/mbostock/4060606)的地图。

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

.counties {
  fill: none;
}

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

</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script>

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

var unemployment = d3.map();

var path = d3.geoPath();

var x = d3.scaleLinear()
    .domain([1, 10])
    .rangeRound([600, 860]);

var color = d3.scaleThreshold()
    .domain(d3.range(2, 10))
    .range(d3.schemeBlues[9]);

var g = svg.append("g")
    .attr("class", "key")
    .attr("transform", "translate(0,40)");

g.selectAll("rect")
  .data(color.range().map(function(d) {
      d = color.invertExtent(d);
      if (d[0] == null) d[0] = x.domain()[0];
      if (d[1] == null) d[1] = x.domain()[1];
      return d;
    }))
  .enter().append("rect")
    .attr("height", 8)
    .attr("x", function(d) { return x(d[0]); })
    .attr("width", function(d) { return x(d[1]) - x(d[0]); })
    .attr("fill", function(d) { return color(d[0]); });

g.append("text")
    .attr("class", "caption")
    .attr("x", x.range()[0])
    .attr("y", -6)
    .attr("fill", "#000")
    .attr("text-anchor", "start")
    .attr("font-weight", "bold")
    .text("Unemployment rate");

g.call(d3.axisBottom(x)
    .tickSize(13)
    .tickFormat(function(x, i) { return i ? x : x + "%"; })
    .tickValues(color.domain()))
  .select(".domain")
    .remove();

d3.queue()
    .defer(d3.json, "https://d3js.org/us-10m.v1.json")
    .defer(d3.tsv, "unemployment.tsv", function(d) { 
      console.log(d);
      unemployment.set(d.id, +d.rate); })
    .await(ready);

function ready(error, us) {
  if (error) throw error;

  svg.append("g")
      .attr("class", "counties")
    .selectAll("path")
    .data(topojson.feature(us, us.objects.counties).features)
    .enter().append("path")
      .attr("fill", function(d) { return color(d.rate = unemployment.get(d.id)); })
      .attr("d", path)
    .append("title")
      .text(function(d) { return d.rate + "%"; });

  svg.append("path")
      .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
      .attr("class", "states")
      .attr("d", path);
}

</script>

我想使用JSON作为我的数据,而不是使用TSV文件。我已经尝试弄清楚如何将脚本转换为使用JSON,但还没有成功。目前,我使用JSON作为结构为:

的示例
[{"id": "01001", "rate": 5.1},
{"id": "01003", "rate": 4.9},
{"id": "01005", "rate": 8.6},
{"id": "01007", "rate": 6.2},
{"id": "01009", "rate": 5.1},
{"id": "01011", "rate": 7.1}]

最终,我希望有一个下拉菜单来选择&#34;列&#34;显示甚至弄清楚如何过滤一年的范围。我的最终JSON结构如下:

[{
   "ID": "02",
   "Volume": "NULL",
   "SubCategory": "Other Housing",
   "Category": "Use",
   "Type": "PAB",
   "date": "2013-12-31",
   "State": "Ohio"
 },
 {
   "ID": "02",
   "Volume": 24800000,
   "SubCategory": "Student Loans",
   "Category": "Use",
   "Type": "PAB",
   "date": "2013-12-31",
   "State": "Ohio"
 },
 {
   "ID": "02",
   "DateExcelNo": "12/31/14",
   "Volume": 440200000,
   "SubCategory": "Mort Rev Bonds",
   "Category": "Use",
   "Type": "PAB",
   "date": "2014-12-31",
   "State": "Ohio"
 },
 {
   "ID": "02",
   "Volume": 1205000000,
   "SubCategory": "Total Cap",
   "Category": "VolumeCapacity",
   "Type": "PAB",
   "date": "2014-12-31",
   "State": "Ohio"
 },
 {   "ID": "01",
   "Volume": "NULL",
   "SubCategory": "Other Housing",
   "Category": "Use",
   "Type": "PAB",
   "date": "2013-12-31",
   "State": "Connecticut"
 },
 {
   "ID": "01",
   "Volume": 24800000,
   "SubCategory": "Student Loans",
   "Category": "Use",
   "Type": "PAB",
   "date": "2013-12-31",
   "State": "Connecticut"
 },
 {
   "ID": "01",
   "DateExcelNo": "12/31/14",
   "Volume": 440200000,
   "SubCategory": "Mort Rev Bonds",
   "Category": "Use",
   "Type": "PAB",
   "date": "2014-12-31",
   "State": "Connecticut"
 },
 {
   "ID": "01",
   "Volume": 1205000000,
   "SubCategory": "Total Cap",
   "Category": "VolumeCapacity",
   "Type": "PAB",
   "date": "2014-12-31",
   "State": "Connecticut"
 },
 {
   "ID": "01",
   "Volume": 663400000,
   "SubCategory": "Total Carryforward to Next Year",
   "Category": "Carryfwd",
   "Type": "PAB",
   "date": "2014-12-31",
   "State": "Connecticut"
 }]

1 个答案:

答案 0 :(得分:4)

这里的问题很简单:d3.json 接受行函数。

我相信您认为,鉴于您在问题中分享了JSON,您可以简单地更改此行......

.defer(d3.tsv, "unemployment.tsv", function(d) { unemployment.set(d.id, +d.rate); })

......对此:

.defer(d3.json, "unemployment.json", function(d) { unemployment.set(d.id, +d.rate); })

但是,这不起作用,因为你不能使用d3.json的那个行函数(第二个逗号之后的所有内容都是行函数)。

<强>解决方案

创建您的JSON文件(此处命名为“unemployment.json”)并在队列中执行此操作:

.defer(d3.json, "unemployment.json")

然后,在ready函数中,将JSON加载为第三个参数(这里我称之为un):

function ready(error, us, un) {

最后,填充d3.map()

un.forEach(function(d) { 
    unemployment.set(d.id, +d.rate); 
});

这是更新的bl.ocks(当然,只有6个县有颜色,因为我使用的JSON只有6个数据点):https://bl.ocks.org/anonymous/211bf9775e61c5b07935536ed1926225

PS:在S.O.每个问题只是一个问题是一个好习惯。因此,我建议您发布另一个询问下拉问题的问题。