如何在 d3 v4 中更新和转换 ordinalScale 轴

How to update & transition ordinalScale axis in d3 v4

我想我会在做一些 d3 工作的同时学习一些关于 ES6 classes 的知识,所以我制作了一个序数条形图 class (fiddle here)。它显示多个系列的数据(例如:

[
    [{"label":"apple", "value" :25},
    {"label":"orange", "value": 16},
    {"label":"pear", "value":19}],

    [{"label":"banana", "value" :12},
    {"label":"grape", "value": 6},
    {"label":"peach", "value":5}]
];

我正在尝试让更新部分正常工作(您提供新数据并且 bars/axis 过渡很好)。不幸的是,许多示例代码是针对 v3 的,它似乎不适用于我正在使用的 v4。具体方法是:

updateData(data){
    //get an array of the ordinal labels out of the data
    let labels = function(data){
        let result = [];
        for(let i=0; i<data.length; i++){
            for (let j=0; j<data[i].length; j++){
                result.push(data[i][j].label);
            }
        }
        return result;
    }(data);

    //loop through the (potentially multiple) series in the data array
    for(let i=0; i<data.length; i++){
        let series = data[i],
            bars = this.svg.selectAll(".series" + i)
        bars
            .data(series)
          .enter().append("rect")
            .attr("class", ("series" + i))
            .classed("bar", true)
          .merge(bars) 
            .attr("x", 0)
            .attr("height", this.y.bandwidth())
            .attr("y", (d) => { return this.y(d.label); })
            .transition().duration(500) //grow bars horizontally on load
            .attr("width", (d) => { return this.x(d.value); });
        bars.exit().remove();
    }

    //update domain with new labels
    this.y.domain(labels);
    //change the y axis
    this.svg.select(".yaxis")
        .transition().duration(500)
        .call(this.yAxis)
}

我正在尝试将更新模式基于 Mike Bostock's code

我收到来自 .call(this.yAxis) 的内部 d3 错误,过渡没有动画,yaxis 没有更新。此外,条形图也不会过渡。怎么了?

几个问题:

  • 在更新数据连接之前更新一个 scaleOrdinal/scaleBand 轴,否则条形将无法找到它们的 y 比例属性 (y(d.yourOrdinalLabel)。因此轴代码需要在条形码之前。
  • bars(或您连接到数据的任何元素)应声明为该连接操作的结果,以便它可以与视觉属性的 .attr() 链接。 let bars = svg.selectAll(".yourClass").data(yourData);
  • 如果您只是要切换现有数据系列的排除,而不是添加新数据,那么在 class 中使用简单的 update 方法更为明智。查看更新后的 fiddle.

Working jsfiddle.