Проблемы с обновлением, вводом, выводом данных и выбором в d3.js

#d3.js

#d3.js

Вопрос:

Я делаю визуальный проект, чтобы показать стихийное бедствие в 1900-2018 годах, используя d3. Я хочу добавить интерактивное действие, которое можно выбрать для отображения первого и последнего года.
Первоначально я создаю изображение следующим образом:

 d3.csv("output.csv", rowConventer, function (data) {
            dataset = data;
            var xScale = d3.scaleBand()
                .domain(d3.range(dataset.length))
                .range([padding, width - padding])
                .paddingInner(0.05);
            var yScale = d3.scaleLinear()
                .domain([0, 
                    d3.max(dataset, function (d) {
                        return d.AllNaturalDisasters;
                    })])
                .range([height - padding, padding])
                .nice();

            stack = d3.stack().keys(["Drought", "Earthquake", "ExtremeTemperature", "ExtremeWeather", "Flood", "Impact", "Landslide", "MassMovementDry", "VolcanicActivity", "Wildfire"]);
            series = stack(dataset);
            gr = svg.append("g");
            groups = gr.selectAll("g")
            .data(series)
            .enter()
            .append("g")
            .style("fill", function(d, i) {
                return colors(i);
            })
            .attr("class", "groups");
            rects = groups.selectAll("rect")
                .data(function(d) { return d; })
                .enter()
                .append("rect")
                .attr("x", function(d, i) {
                    return xScale(i);
                })
                .attr("y", function(d) {
                    return yScale(d[1]);
                })
                .attr("height", function(d) {
                    return yScale(d[0]) - yScale(d[1]);
                })
                .attr("width", xScale.bandwidth())
                .append("title")
                .text(function (d) {
                    var rect = this.parentNode;// the rectangle, parent of the title
                    var g = rect.parentNode;// the g, parent of the rect.
                    return d.data.Year   ", "   d3.select(g).datum().key   ","   (d[1]-d[0]);
                });
           d3.select("button")
               .on("click", choosePeriod);
  

Я упростил некоторый код, чтобы упростить свой вопрос. В последней строке я добавляю прослушиватель событий для достижения того, что я описал выше. И функция обновления — choosePeriod. Теперь это выглядит следующим образом:

     function choosePeriod() {
        firstYear = parseInt(document.getElementById("FirstYear").value);
        lastYear = parseInt(document.getElementById("LastYear").value);
        d3.csv("output.csv", rowConventer, function (newdata) {
            dataset = newdata;
            series=stack(dataset);
            groups.data(series);
            groups.selectAll("rect")
                .data(function (d) {
                    return d;
                })
                .enter()
                .append("rect")
                .attr("x", function(d, i) {
                    return xScales(i);
                })
                .attr("y", function(d) {
                    return yScales(d[1]);
                })
                .attr("height", function(d) {
                    return yScales(d[0]) - yScales(d[1]);
                })
                .attr("width", xScales.bandwidth())
                .append("title")
                .text(function (d) {
                    var rect = this.parentNode;// the rectangle, parent of the title
                    var g = rect.parentNode;// the g, parent of the rect.
                    return d.data.Year   ", "   d3.select(g).datum().key   ","   (d[1]-d[0]);
                });
            groups.selectAll("rect")
                    .data(function (d) {
                        return d;
                    })
                    .exit()
                    .remove();

        })
    }
  

Изменение набора данных достигается с помощью rowConventer , что не важно в этом вопросе. Теперь функция choosePeriod работает не так, как предполагалось! enter И exit и update все работают неправильно! Вся картина в беспорядке! Я хочу, например, чтобы, если я ввожу firstYear=1900 и lastYear=2000 , то изображение должно быть обновлено с отображением периода 1900-2000. Как я могу этого добиться?

Я незнаком с расположением всей структуры, я имею в виду, что в каком-то месте использование d3.select() by class или id вместо label лучше, верно?

Ответ №1:

Похоже, вы разобрались с выборками ввода и выхода. Единственное, чего вам не хватает, — это выбор обновления, который будет иметь дело с прямоугольниками, которые уже существуют и не нуждаются в добавлении или удалении. Для этого скопируйте шаблон обновления, но просто удалите бит enter().append(), например:

 groups.selectAll("rect")
                .data(function (d) {
                    return d;
                })
                .attr("x", function(d, i) {
                    return xScales(i);
                })
                .attr("y", function(d) {
                    return yScales(d[1]);
                })
                .attr("height", function(d) {
                    return yScales(d[0]) - yScales(d[1]);
                })
                .attr("width", xScales.bandwidth())
                .append("title")
                .text(function (d) {
                    var rect = this.parentNode;// the rectangle, parent of the title
                    var g = rect.parentNode;// the g, parent of the rect.
                    return d.data.Year   ", "   d3.select(g).datum().key   ","   (d[1]-d[0]);
                })
  

Комментарии:

1. на самом деле, enter (), exit(), update () работают некорректно. И это то, что меня озадачивает. Спасибо и извините, что забыли сказать это в первый раз!

2.Подождите!! Извините, что не попробовал ваш метод десять часов назад, я попробовал это только сейчас update enter , используя последовательность exit and, и она работает правильно!