d3 v5: как переходить только при изменении определенного атрибута? - PullRequest
1 голос
/ 05 июля 2019

У меня есть карта с кружком в центре каждой страны.Я применяю анимацию, которая обновляет круги каждые 3 секунды, следуя шаблону общего обновления Майка Бостока.Однако моя проблема заключается в том, что я хочу применить переход к старым элементам, которые остаются на диаграмме (т.е. не являются частью exit()), но только для тех, которые имеют изменение в определенном атрибуте (поскольку этот атрибут определяетцвет круга).Я подумал, что должен сохранить старое значение в качестве атрибута в круге, а затем просто сравнить это значение атрибута с вновь назначенным значением из обновленных данных.

Однако, когда я использую обычное предложение js ifон предоставляет мне только первый элемент, что означает, что при изменении значения этого круга все остальные круги также получат переход.

Как я могу проверить между старым и новым значением внутри этого шаблона?

Вот пример кода:

//DATA JOIN                 
var countryCircles = circleCont.selectAll(".dataCircle")
    .data(filData, function(d){ return d.id})

//EXIT OLD CIRCLES THAT ARE NOT INCLUDED IN NEW DATASET
countryCircles.exit()
    .transition()
        .ease(d3.easeLinear)
        .duration(500)
        .attr("r",0)
        .remove()

//CHECK IF OLD CIRCLES THAT ARE INCLUDED CHANGED THE CRITICAL ATTRIBUTE VALUE (main)
if (countryCircles.attr('main') != countryCircles.data()[0].main) {

    countryCircles
        .attr("main", function(d) {return d.main})
        .attr("id", function(d) {return "circle" + d.id})
        .attr("class","dataCircle")
        .transition()
            .ease(d3.easeLinear)
            .duration(500)
                .ease(d3.easeLinear)
                .attr("r",0)
                .transition()
                    .duration(500)
                    .ease(d3.easeLinear)
                    .attr("r",10)
                    .style("fill", function(d) {
                                            if (d.main === "nodata") {
                                                return "grey"
                                            } else {
                                                return color_data.find(function (y) {
                                                      return y.main === d.main;
                                                  }).color;
                                            }
                                        })

} else {
    countryCircles
        .attr("main", function(d) {return d.main})
        .attr("id", function(d) {return "circle" + d.id})
        .attr("class","dataCircle")
}

//CREATE CIRCLES THAT ARRE NEW IN THE UPDATED DATASET
var newCircle = countryCircles.enter()
   .append("circle")
   .attr("class","dataCircle")
   .attr("cx", getCX)
   .attr("cy", getCY)
   .attr("id", function(d) {return "circle" + d.id})
   .attr("main", function(d) {return d.main})
   .style("cursor","crosshair")
   .attr("r", 0)    
   .transition()
        .delay(500)
        .duration(500)
        .ease(d3.easeLinear)
        .attr("r",10)
        .style("fill", function(d) {
                            if (d.main === "nodata") {
                                return "grey"
                            } else {
                                return color_data.find(function (y) {
                                      return y.main === d.main;
                                  }).color;
                            }
                        })

1 Ответ

2 голосов
/ 05 июля 2019

ОК, решение было несколько прямолинейным (а я был слепым ...).

Вместо использования оператора if для отдельного элемента, я использую функцию each() и в нем проверяюизменение.

...
//CHECK IF OLD CIRCLES THAT ARE INCLUDED CHANGED THE CRITICAL ATTRIBUTE VALUE (main)
countryCircles.each(function(d) {
    if (d3.select(this).attr('main') != d3.select(this).data()[0].main) {
    ...

...