javascript - 如何在气泡图中按状态和在行/列中定位气泡
问题描述
我已经使用以下教程让我们制作一个气泡图来创建一个带有矩形而不是圆形的状态图来代表印度的选区。我不想根据选区定位矩形,而是将它放在每个状态上方的行/列中彼此相邻的位置。
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/
解决方案
这是从您的代码中分叉的小提琴。
首先让我们遍历选区并按州对它们进行分组。
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
,您可以根据您的要求更改此逻辑。然后我们根据行数和列数计算initialX
并确定第一个点应该去哪里。initialY
然后我们使用、和属性为map
每个选区返回一个新对象。和值被修改为根据它们的索引向右和向下移动每个项目。x
y
state
constituency
x
y
.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 });
推荐阅读
- php - 双 Foreach 中第一个循环的奇怪数学
- java - 使用 servlet 前缀配置 Spring Cloud 数据流
- ios - 我的应用在 iOS 10 及更早版本上崩溃。我可以从哪里开始寻找调试呢?
- r - 根据其他数据框中的列表子集数据框
- python - pygame没有出现
- c# - 如何在淘汰赛 foreach 绑定中使用表单
- reactjs - 发布了一个新的 npm 包。安装和使用时,出现 SyntaxError :“Unexpected token”
- android - Flutter:如果页面已经被压入堆栈,如何重新打开它们?
- algorithm - 具有给定 OR 值的对数
- c# - GetType 在 C# 中的每个对象中是如何实现的?