Я использую D3.js для создания интерактивного графика, который я пытаюсь сделать похожим на этот график пчеловодства из New York Times: https://archive.nytimes.com/www.nytimes.com/interactive/2013/05/25/sunday-review/corporate-taxes.html. Используя следующий код, я могу сгенерироватьправильное пчелиное тепло с моими узлами, когда они представляют собой одну группу вдоль одной оси (как в «Общей картине» на графике NYT).
Вот мой рабочий код:
// index.html
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
font: 10px sans-serif;
}
.cells path {
fill: none;
pointer-events: all;
}
.cells :hover circle {
fill: red;
}
</style>
<head>
<title>Beeswarm Plot</title>
</head>
<body>
<svg width="960" height="200"></svg>
</body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="PapaParse-4.6.0/papaparse.js"></script>
<script>
var dataset = new Array();
var sortableData = new Array();
var authors = [];
var magazines = [];
var genres = [];
var numAuthors, numMagazines, numGenres;
d3.csv("dataset.csv", function(data){
dataset = data;
for(var i=0; i<dataset.length; i++){
if(!authors.includes(dataset[i].author))
authors.push(dataset[i].author);
if(!magazines.includes(dataset[i].magazine))
magazines.push(dataset[i].magazine);
if(!genres.includes(dataset[i].genre))
genres.push(dataset[i].genre);
}
sortableData = [authors.sort(), magazines.sort(), genres.sort()];
numAuthors = sortableData[0].length;
numMagazines = sortableData[1].length;
numGenres = sortableData[2].length;
});
var svg = d3.select("svg"),
margin = {top: 40, right: 40, bottom: 40, left: 40},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom;
var formatValue = d3.format(",d");
var x = d3.scaleLinear()
.rangeRound([0, width]);
// Start for loop here
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("dataset.csv", type, function(error, data) {
if (error) throw error;
x.domain(d3.extent(data, function(d) { return d.year; }));
var simulation = d3.forceSimulation(data)
.force("x", d3.forceX(function(d) { return x(d.year); }).strength(1))
.force("y", d3.forceY(height / 2))
.force("collide", d3.forceCollide(16))
.stop();
for (var i = 0; i < 120; ++i) simulation.tick();
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0,0)")
.call(d3.axisTop(x).ticks(6).tickFormat(d3.format("d")));
var cell = g.append("g")
.attr("class", "cells")
.selectAll("g").data(d3.voronoi()
.extent([[-margin.left, -margin.top], [width + margin.right, height + margin.top]])
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.polygons(data)).enter().append("g");
cell.append("circle")
.attr("r", 15)
.attr("cx", function(d) { return d.data.x; })
.attr("cy", function(d) { return d.data.y; });
cell.append("path")
.attr("d", function(d) { return "M" + d.join("L") + "Z"; });
cell.append("title")
.text(function(d) { return d.data.title + "\n" + formatValue(d.data.year); });
});
function type(d) {
if (!d.year) return;
d.year = +d.year;
return d;
}
</script>
Каждый из узлов в dataset.csv представляет истории из старых научно-фантастических / фантастических журналов со свойствами, такими как название, год, автор и жанр:
//dataset.csv
title,year,author,magazine,genre
"Nightfall",1941,"Asimov","Astounding","Sci-Fi"
"Marooned Off Vesta",1939,"Asimov","Amazing","Sci-Fi"
"Homo Sol",1940,"Asimov","Astounding","Sci-Fi"
"The Word of Unbinding",1964,"Le Guin","Fantastic","Fantasy"
"Robbie",1939,"Asimov","Astounding","Sci-Fi"
Мой рабочий код отображает все узлы вдоль одногогоризонтальная ось, которая сортирует их по годам.Тем не менее, я также хочу иметь возможность сортировать свои узлы по автору, разбивая общий вид на отдельные графики пчеловодства, каждый из которых отображает только истории определенного автора (аналогично «View By Industry» в примере NYT),Как бы я поступил так?