Изменение порядка элементов в DOM
Чтобы изменить порядок элементов в DOM с помощью d3, вы можете использовать selection.sort и selection.order :
// Sort & then order:
selection.sort(function(a,b) {
return a.property - b.property;
})
.order();
Selection.sort сортирует выборку на основе связанных данных, a
и b
каждый представляют данные, привязанные к одному элементу.Результирующее поведение, по сути, такое же, как Array.sort, но вместо использования массива вы сортируете элементы в выделении, используя их связанные данные.Содержимое функции, предоставляемой selection.sort (функция сравнения), определяет порядок сортировки:
Функция сравнения, по умолчанию восходящая, передается для сравнения данных двух элементов a и b.Он должен возвращать либо отрицательное, положительное или нулевое значение.Если отрицательно, то a должно быть до b;если положительный, то a должно быть после b;в противном случае a и b считаются равными, а порядок произвольным.( docs )
Как только у нас будет отсортированный выбор, мы можем применить selection.order()
, который повторно вставляет каждый элемент в DOM в соответствии с порядком выбора.Помните, что элементы, нарисованные первыми, могут быть покрыты элементами, нарисованными позже - первое в выделении означает потенциально под всем.
Так что, если бы у нас было что-то подобное, где перекрывающиеся столбцы рисуются последовательно на основе порядкамассив данных:
![enter image description here](https://i.stack.imgur.com/FJY79.png)
var bars = [
{value: 100},
{value: 50},
{value: 200},
{value: 70},
{value: 40},
{value: 120}
];
var height = 200;
var width = 500;
var svg = d3.select("body")
.append("svg")
.attr("height",height)
.attr("width",width);
var bars = svg.selectAll("rect")
.data(bars)
.enter()
.append("rect")
.attr("width", 45)
.attr("height", function(d) { return d.value; })
.attr("y", function(d) { return height-d.value; })
.attr("x", function(d,i) { return i * 30 + 50; })
.attr("fill", function(d,i){ return d3.schemeCategory10[i]; })
.attr("stroke","black")
.attr("stroke-width",1);
// Order the bars:
bars.sort(function(a,b) {
return b.value - a.value;
}).order();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Мы можем подтянуть маленькие столбики, скажем, для большей наглядности с сортировкой и порядком:
![enter image description here](https://i.stack.imgur.com/pK43a.png)
var bars = [
{value: 100},
{value: 50},
{value: 200},
{value: 70},
{value: 40},
{value: 120}
];
var height = 200;
var width = 500;
var svg = d3.select("body")
.append("svg")
.attr("height",height)
.attr("width",width);
var bars = svg.selectAll("rect")
.data(bars)
.enter()
.append("rect")
.attr("width", 45)
.attr("height", function(d) { return d.value; })
.attr("y", function(d) { return height-d.value; })
.attr("x", function(d,i) { return i * 30 + 50; })
.attr("fill", function(d,i){ return d3.schemeCategory10[i]; })
.attr("stroke","black")
.attr("stroke-width",1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Перестановка на основе заказа
Как вы можете видеть выше, это не сбрасывает xили y атрибут каждой полосы, чтобы отразить порядок на z (как в вашем примере).Как и в моем базовом примере выше, мы можем сбросить значения x на основе i (это можно сделать и путем изменения масштаба, но этого достаточно, чтобы быть отдельным вопросом и ответом):
var bars = [
{value: 100},
{value: 50},
{value: 200},
{value: 70},
{value: 40},
{value: 120}
];
var height = 200;
var width = 500;
var svg = d3.select("body")
.append("svg")
.attr("height",height)
.attr("width",width);
var bars = svg.selectAll("rect")
.data(bars)
.enter()
.append("rect")
.attr("width", 45)
.attr("height", function(d) { return d.value; })
.attr("y", function(d) { return height-d.value; })
.attr("x", function(d,i) { return i * 30 + 50; })
.attr("fill", function(d,i){ return d3.schemeCategory10[i]; })
.attr("stroke","black")
.attr("stroke-width",1)
bars = bars.sort(function(a,b) {
return a.value - b.value;
}).order();
bars.transition()
.attr("x", function(d,i) { return i * 30 + 50; })
.delay(500)
.duration(2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
См. Также: вопрос и ответ, который во многом похож на ваш пример: сортировка и упорядочениеиспользуется при переходе как длины слитков, так и порядка слитков.