d3.js
шаблон обновления
Поиск…
Синтаксис
- selection.enter ()
- selection.exit ()
- selection.merge ()
Обновление данных: базовый пример ввода, обновления и выбора выхода
Создание диаграммы, отображающей статический набор данных, относительно просто. Например, если у нас есть этот массив объектов в качестве данных:
var data = [
{title: "A", value: 53},
{title: "B", value: 12},
{title: "C", value: 91},
{title: "D", value: 24},
{title: "E", value: 59}
];
Мы можем создать гистограмму, в которой каждый бар представляет собой меру с названием «title», а ее ширина представляет значение этой меры. Поскольку этот набор данных не изменяется, наша гистограмма имеет только «ввод»:
var bars = svg.selectAll(".bars")
.data(data);
bars.enter()
.append("rect")
.attr("class", "bars")
.attr("x", xScale(0))
.attr("y", function(d){ return yScale(d.title)})
.attr("width", 0)
.attr("height", yScale.bandwidth())
.transition()
.duration(1000)
.delay(function(d,i){ return i*200})
.attr("width", function(d){ return xScale(d.value) - margin.left});
Здесь мы устанавливаем ширину каждого столбца равным 0 и, после перехода, к его окончательному значению.
Это ввести выбор, один, достаточно, чтобы создать нашу диаграмму, которую вы можете увидеть в этой скрипке .
Но что, если мои данные меняются?
В этом случае нам нужно динамически менять наш график. Лучший способ сделать это - создать «ввод», «обновление» и «выход». Но перед этим нам нужно внести некоторые изменения в код.
Сначала мы переместим изменяющиеся части внутри функции с именем draw()
:
function draw(){
//changing parts
};
Эти «меняющиеся части» включают:
- Выбор входа, обновления и выхода;
- Область каждой шкалы;
- Переход оси;
Внутри этой функции draw()
мы вызываем другую функцию, которая создает наши данные. Здесь это просто функция, которая возвращает массив из 5 объектов, выбирая случайным образом 5 букв из 10 (сортировка по алфавиту) и для каждого из них значение от 0 до 99:
function getData(){
var title = "ABCDEFGHIJ".split("");
var data = [];
for(var i = 0; i < 5; i++){
var index = Math.floor(Math.random()*title.length);
data.push({title: title[index],
value: Math.floor(Math.random()*100)});
title.splice(index,1);
}
data = data.sort(function(a,b){ return d3.ascending(a.title,b.title)});
return data;
};
И теперь, давайте перейдем к нашим выборам. Но перед этим, предостережение: чтобы поддерживать то, что мы называем постоянством объекта , мы должны указать ключевую функцию как второй аргумент selection.data:
var bars = svg.selectAll(".bars")
.data(data, function(d){ return d.title});
Без этого наши бары не будут проходить плавно, и будет сложно следить за изменениями в оси (вы можете видеть, что удаление второго аргумента в скрипке ниже).
Итак, после правильной настройки наших var bars
, мы можем иметь дело с нашими выборами. Это выбор выхода:
bars.exit()
.transition()
.duration(1000)
.attr("width", 0)
.remove();
И это выбор ввода и обновления (в D3 v4.x выбор обновления сливается с выбором ввода с помощью merge
):
bars.enter()//this is the enter selection
.append("rect")
.attr("class", "bars")
.attr("x", xScale(0) + 1)
.attr("y", function(d){ return yScale(d.title)})
.attr("width", 0)
.attr("height", yScale.bandwidth())
.attr("fill", function(d){ return color(letters.indexOf(d.title)+1)})
.merge(bars)//and from now on, both the enter and the update selections
.transition()
.duration(1000)
.delay(1000)
.attr("y", function(d){ return yScale(d.title)})
.attr("width", function(d){ return xScale(d.value) - margin.left});
Наконец, мы вызываем функцию draw()
каждый раз, когда нажимаем кнопку:
d3.select("#myButton").on("click", draw);
И это сценарий, показывающий все эти 3 выбора в действии.
Слияние
Шаблон обновления в версии 3 D3
Правильное понимание того, как работают «ввод», «обновление» и «выход», имеет основополагающее значение для правильного изменения dataviz с использованием D3.
Начиная с версии 3 (на самом деле, начиная с версии 2), этот фрагмент может устанавливать переходы для выбора «ввести» и «обновить» ( здесь присутствует живая демонстрация ):
var divs = body.selectAll("div")
.data(data);//binding the data
divs.enter()//enter selection
.append("div")
.style("width", "0px");
divs.transition()
.duration(1000)
.style("width", function(d) { return d + "px"; })
.attr("class", "divchart")
.text(function(d) { return d; });
Предоставление этого результата после перехода:
Но что происходит с точно таким же кодом, если мы используем D3 версии 4? Вы можете увидеть это в этой живой демо : ничего !
Зачем?
Изменения в шаблоне обновления в версии D3 версии 4
Давайте проверим код. Во-первых, у нас есть divs
. Этот выбор привязывает данные к <div>
.
var divs = body.selectAll("div")
.data(data);
Затем у нас есть divs.enter()
, который представляет собой выбор, содержащий все данные с непревзойденными элементами. Этот выбор содержит все divs в первый раз, когда мы вызываем функцию draw
, и устанавливаем их ширину на ноль.
divs.enter()
.append("div")
.style("width", "0px");
Затем у нас есть divs.transition()
, и здесь у нас есть интересное поведение: в версии 3 D3, divs.transition()
делает все <div>
в выборе «enter» изменяющимся до конечной ширины. Но это не имеет смысла! divs
не содержит выбор «enter» и не должен изменять какой-либо элемент DOM.
Существует причина, почему это странное поведение было введено в D3 версии 2 и 3 ( источник здесь ), и он был «исправлен» в версии D3 версии 4. Таким образом, в живой демо выше ничего не происходит, и это ожидается! Кроме того, если вы нажмете кнопку, появятся все предыдущие шесть баров, потому что теперь они находятся в «обновлении», а не в «enter».
Для перехода, действующего над выбором «ввести», мы должны создать отдельные переменные или, более простой подход, объединить выбор :
divs.enter()//enter selection
.append("div")
.style("width", "0px")
.merge(divs)//from now on, enter + update selections
.transition().duration(1000).style("width", function(d) { return d + "px"; })
.attr("class", "divchart")
.text(function(d) { return d; });
Теперь мы объединили опции «ввести» и «обновление». Посмотрите, как это работает в этой живой демонстрации .