JavaScript / D3.js : Данные не обновляются при нажатии кнопки, вместо этого отображаются новые позиции

#javascript #d3.js #svg #append #bar-chart

#javascript #d3.js #svg #добавить #гистограмма

Вопрос:

При нажатии кнопки как красная женщина (непривитая), так и синяя женщина (привитая) должны обновляться, чтобы отразить новое значение. В настоящее время при нажатии кнопки красная женщина обновляется, но синяя женщина воссоздается в том месте, в которое она должна быть обновлена. Как я могу заставить синюю женщину переходить и обновляться, как красная женщина?

Здесь вы можете увидеть, где воссоздана синяя женщина:
Здесь вы можете увидеть, где воссоздана синяя женщина

Я создал две глобальные переменные:

  var numOfPartner = 'zero';
 var status = 0;
  

Здесь создаются данные при загрузке и вводится красное изображение:

 d3.csv("link to data", function(error, data) {

    if (error) {
      console.log("error reading file");
    }

    data.sort(function(a, b) {
      return d3.descending( a.status,  b.status);
    });

    // you should calculate using d3.max for your data
    widthScale.domain([0, d3.max(data, function(d) {
      return  d.start;
    })]);

    heightScale.domain(data.map(function(d) {
      return  d.average;
    }).slice(1));

    var rects = svg.selectAll("rect")
    .data(([data[0]]))
    .enter()
    .append("rect");

    rects
      .attr("x", 0)
      .attr("y", function(d) {
        return heightScale(d.status);
      })
      .attr("width", function(d) {
        return widthScale( d.average);
      })
      .attr("height", heightScale.rangeBand());

    svg.selectAll("text")
      .attr("class", "label")
      .data(([data[0]]))
      .enter()
      .append("text")
      .text(function(d) {
        return  d.average   " %";
      })
      .attr("x", function(d) {
        return widthScale( d.average)   5;
      })
      .attr('y', '-45')
      .attr("fill", "#8a8c8e")
      .attr("font-size", "24")
      .attr("font-weight", "700")

    // Style the axis
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0,"   height   ")")
      .call(xAxis)
      .attr("fill", "#808285");

    // Label below x axis
    svg.append("text")
      .attr("class", "xlabel")
      .attr("transform", "translate("   width / 2   " ,"  
            height   ")")
      .style("text-anchor", "middle")
      .attr("dy", "0")
      .text("  ")
      .attr("fill", "#5582b0")
      .attr("font-weight", "600");

    svg.selectAll("image1")
      .data(([data[0]]))
      .enter()
      .append("svg:image")
      .attr("x", function(d) {
        return widthScale( d.average) - 45;
      })
      .attr('y', '-40')
      .attr("height", 200)
      .attr("width", 115)
      .attr("xlink:href", "link to red woman");
  

Вот функция обновления кнопки, в которой красная женщина работает, а синяя — нет:

 d3.selectAll("button").on("click", function() {
     if (this.id == "unvaccinated")
         status = 0;
     else if (this.id == "vaccinated") {
         status = 1;
     } else {
         numOfPartner = this.id;
     }
     svg.selectAll("image2")
         .data(([data[1]]))
         .enter()
         .append("svg:image")
         .attr("x", function(d) {
             return widthScale(data[1][numOfPartner]) - 45;
         })
         .attr('y', '-40')
         .attr("height", 200)
         .attr("width", 115)
         .attr("xlink:href", "link to blue woman");

     rects
         .data(data)
         .transition()
         .duration(1000)
         .ease("linear")
         .attr("width", function(d) {
             return widthScale(data[status][numOfPartner]);
         });

     svg.selectAll("text")
         .data(([data[0]]))
         .transition()
         .duration(1000)
         .ease("linear")
         .attr("x", function(d) {
             return widthScale(data[status][numOfPartner])
         })
         .text(function(d) {
             return data[status][numOfPartner]   " %"
         });

     svg.selectAll("image")
         .data(([data[0]]))
         .transition()
         .duration(1000)
         .ease("linear")
         .attr("x", function(d) {
             //get correct number     
             return widthScale(data[status][numOfPartner]) - 45;
         });


     svg.selectAll("image2")
         .data(([data[1]]))
         .transition()
         .duration(1000)
         .ease("linear")
         .attr("x", function(d) {
             //get correct number     
             return widthScale(data[1][numOfPartner]) - 45;
         });

     });

});
  

Я пытался поиграть с функцией нажатия кнопки on, а также с извлекаемыми данными, но мне не повезло.

Ответ №1:

Трудно на 100% сказать, что не так, не видя данных или живой демонстрации, но я вижу проблему в обратном вызове click. Переместите этот код в обратный d3.csv вызов:

  svg.selectAll("image2")
     .data(([data[1]]))
     .enter()
     .append("svg:image")
     .attr("x", function(d) {
         return widthScale(data[1][numOfPartner]) - 45;
     })
     .attr('y', '-40')
     .attr("height", 200)
     .attr("width", 115)
     .attr("xlink:href", "link to blue woman");
  

Это добавляет новый элемент в ваш SVG, а не делает обновление. Вероятно, это не то, что вы хотите при обратном вызове click. Это должно быть где-то в функции инициализации. У вас есть правильный код обновления позже в обратном вызове, но это не будет работать должным образом, потому что был добавлен новый элемент.

Еще одна вещь, я заметил, что вы используете image1 в обратном вызове данных и image1 в обратном вызове click. Убедитесь, что это правильно, а не опечатка.