Вот скрипка разветвленная из вашего кода.
Сначала давайте проведем итерации по округам и сгруппируем их по штатам.
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 });