如何按状态在气泡图中以及在行/列中放置气泡

时间:2019-05-01 08:18:33

标签: javascript d3.js svg

我已使用以下教程Let's make a bubble map创建了一个矩形而不是圆形的州图,以代表印度的选区。我不想将矩形基于选区放置,而是将其在每个状态上方的行/列中彼此相邻放置。

svg.selectAll(".state-stroke")
            .data(stateboundary).enter().append("path")
            .attr("d", geoPath)
            .attr("class", "state-stroke")
            .attr('stroke', "#888888")
            .attr('stroke-width', "0.8")
            .attr('fill', "none")
            .attr('stroke-opacity', "1")

svg.selectAll(".name").data(pcCentroid)
            .enter().append("rect")
            .attr("x", function(d){ return d[0]; })
            .attr("y", function (d){ return d[1]; })
            .attr("width", "3")
            .attr("height", "3")
            .attr("class", function(d,i){
                return stateboundary[i]['properties']['ST_CODE']
            });

我在此处包括了完整的代码 https://jsfiddle.net/diviseed/4qhnakwb/2/

现在看起来像下面的地图 enter image description here

我想要的结果如下所示 enter image description here

1 个答案:

答案 0 :(得分:1)

这里是您代码中的a fiddle分叉。

首先让其遍历选区并按州对它们进行分组。

var constituenciesByState = {};
pathshape.objects.pcboundary.geometries
  .forEach(function(pc){
     var code = pc.properties.ST_CODE;
     if (!constituenciesByState[code]) {
        constituenciesByState[code] = [];
     }
     constituenciesByState[code].push(pc);
  });

然后修改d3代码,而不是从pcCentroid数据开始,而不是从stateCentroid数据开始,并为每个状态附加一个新的svg元素。

svg.selectAll(".name").data(stateCentroid)
  .enter().append("svg") 

然后,我们为每个选区生成嵌套数据。首先获取当前状态的代码,然后获取相关选区的数组。然后我们计算rowLength,您可以根据需要更改此逻辑。然后,根据行和列的数量,计算initialXinitialY以确定第一个点应该到达的位置。然后,我们使用map为每个选区返回一个新对象,这些对象具有xystateconstituency属性。修改了xy的值,以根据它们的索引左右移动每个项目。

.data(function(d, index) { 
  var stateCode = stateboundary[index]['properties']['ST_CODE'];
  var constituencies = constituenciesByState[stateCode];

  var rowLength = Math.ceil(Math.sqrt(constituencies.length));  // rectangles per row
  var offset = 5;  // spacing between start of each rectangle

  var numCols = Math.min(constituencies.length, rowLength);
  var numRows = Math.ceil(constituencies.length/rowLength);

  var initialX = d[0] - (numCols * offset)/2;
  var initialY = d[1] - (numRows * offset)/2;

  return constituencies
    .map(function(c, i) {
    return {
      x : initialX + ((i % rowLength) * offset),
      y : initialY + Math.floor(i / rowLength) * offset,
      constituency: c.properties.PC_CODE,
      state: stateCode
    }
  }); 
 })

然后对每个点的格式所做的更改稍作修改,并在工具提示中显示选区代码:

.attr("x", function(d){ return d.x })
.attr("y", function (d){ return d.y })
.attr("width", "3")
.attr("height", "3")
.attr("class", function(d,i){
    return d.state;
})
.append("title")
.text(function(d) { return d.constituency });