Я делаю визуализацию, показывающую наиболее распространенные жанры концертов в данном городе. В настоящее время я показываю данные, используя диаграмму с областями d3.
Чтобы сделать визуализацию более тематически подходящей, я решил попытаться сделать ее похожей на звуковую волну, и здесь я наткнулся на камень преткновения.
В настоящее время я все еще использую диаграмму с областями, отраженную по оси X, и это выглядит хорошо для некоторых городов, когда данные разбросаны по значительному промежутку времени. Однако это выглядит не совсем правильно, если смотреть на большой город с большим количеством событий.
Я думаю, что я хочу сделать, это нарисовать меньшие прямоугольники внутри границ диаграммы с областями, сначала я подумал, что могу использовать область SVG в качестве маски, но тогда вершины прямоугольников будут наклонены...
Также думал просто сделать гистограмму с несколькими столбцами для каждой точки данных, но я думаю, что это приведет к большим сдвигам между каждой точкой. Я хочу по-прежнему иметь наклоны между точками данных, которые я получаю из области/линейной диаграммы.
У кого-нибудь есть предложения? Моя цель состояла бы в том, чтобы получить визуализацию, как показано ниже:



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Один из подходов заключается в использовании данных не для создания диаграммы, а для создания зубчатой линейной шкалы x -> y. Затем сгенерируйте желаемое количество прямоугольников и сопоставьте их индексы с позицией x. Остальное просто — просмотрите индексы, сопоставьте их с x, сопоставьте полученный x с y, и все готово.
<!DOCTYPE html>
<head>
<meta charset = "utf-8">
<script src = "https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
<script>
var data = [{
x: 1,
y: 2
}, {
x: 5,
y: 10
}, {
x: 15,
y: 5
}, {
x: 20,
y: 13
}, {
x: 25,
y: 4
}];
var rectCount = 8;
var yScale = d3.scaleLinear()
.domain(data.map(function(d){ return d.x; }))
.range(data.map(function(d){ return d.y; }));
var xScale = d3.scaleBand()
.domain(d3.range(rectCount))
.paddingInner(0.5)
.range([d3.min(data, function(d) {return d.x; }),
d3.max(data, function(d) {return d.x; })]);
var svg = d3.select("body").append("svg")
.attr("width", 100)
.attr("height", 100)
.attr('viewBox', '-5 -20 35 40');
var chartData = d3.range(rectCount).map(function(i){
var x = xScale(i);
var width = xScale.bandwidth();
var y = yScale(x);
var height = y*2;
return {
x: x,
y: y,
width: width,
height: height
};
});
svg.selectAll('rect')
.data(chartData)
.enter()
.append('rect')
.attr('x', function(d) { return d.x; })
.attr('y', function(d) { return -d.y; })
.attr('width', function(d) { return d.width; })
.attr('height', function(d) { return d.height; })
</script>
</body>