Поиск…


Синтаксис

  • 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
};

Эти «меняющиеся части» включают:

  1. Выбор входа, обновления и выхода;
  2. Область каждой шкалы;
  3. Переход оси;

Внутри этой функции 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; });

Теперь мы объединили опции «ввести» и «обновление». Посмотрите, как это работает в этой живой демонстрации .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow