简体   繁体   中英

d3.js ordinal axis is not updated correctly

I created a simple, updatedable d3.js bar chart. Except for the x-axis, it works fine.

When I remove bars from the chart, the corresponding axis labels are not removed.

初始条第一次用错误的轴移除了条形图

But when I remove bars for the second time, the labels of the bars that were removed in the first run are removed from the axis.

用正确的轴第二次移除吟游诗人

What is happening here, and why?

See a working demo here: http://jsfiddle.net/vACua/4/

The js code would be the following:

    var BarChart = function (config) {

    var data,
    svg,
    xScale,
    yScale,
    yAxis,
    xAxis;

   svg = d3.select('#' + config.targetElement).append('svg');

    svg.attr("width", config.width + config.margin.left + config.margin.right)
        .attr("height", config.height + config.margin.top + config.margin.bottom)
        .attr("transform", "translate(" + config.margin.left + "," + config.margin.top + ")");

    xScale = d3.scale.ordinal();
    yScale = d3.scale.linear();

    xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(-config.height, 0).tickPadding(6);
    svg.append('g').classed('x-axis-group axis', true);

    svg.append("g")
        .classed("x axis", true)
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);


    // All methods and members defined here are public
    return {
        setData: function (newData) {
            data = newData;
            this.updateChart();
        },
        updateChart: function () {
            var xDomain = data.map(function (d) {
                return d.name;
            }),
                yDomain = data.map(function (d) {
                    return d.value;
                });



            xScale.domain(xDomain)
                .rangeRoundBands([config.margin.left, config.width], 0.05);

            yScale.domain([0, d3.max(data, function (d) {
                return d.value;
            })])
                .range([config.height, 0]);


            xAxis.scale(xScale)
                .orient("bottom")
                .tickSize(-config.height, 0)
                .tickPadding(6);

            var dataSections = svg.selectAll("g.bar")
                .data(data, function (d) {
                return d.name;
            });


            // adding new bars
            dataSections.enter()
                .append('g')
                .attr('class', 'bar')
                .append("rect")
                .attr("height", 0);

            var transition = svg.transition().duration(750);

            transition.selectAll("g.bar").select('rect')
                .attr("x", function (d, i) {
                return xScale(d.name);
            })
                .attr("y", function (d) {
                return yScale(d.value);
            })
                .attr("width", xScale.rangeBand())
                .attr("height", function (d) {
                return height - yScale(d.value);
            });


            dataSections.exit().transition().remove();



            svg.select('.x.axis')
                .transition()
                .duration(500)
                .attr({
                transform: 'translate(0,' + (config.height) + ')'
            })
                .call(xAxis);




        }
    };
};

var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 40
},
width = 960 - margin.left - margin.right,
    height = 250 - margin.top - margin.bottom;


amount = 15;

function init() {
    var margin = {
        top: 20,
        right: 20,
        bottom: 30,
        left: 40
    },
    width = 400 - margin.left - margin.right,
        height = 250 - margin.top - margin.bottom;

    var chart = BarChart({
        targetElement: 'foo',
        margin: margin,
        width: width,
        height: height
    });

    setRandomData = function () {
        var data = [];
        for (var i = 0; i <= amount; i++) {
            data.push({
                name: "a" + i,
                value: Math.floor((Math.random() * 300) + 1)
            });
        }
        amount = amount - 5;

        chart.setData(data);
    }
}

init();
setRandomData();
setTimeout(setRandomData, 2000);
setTimeout(setRandomData, 4000);

Ok, I have absolutely no clue why but moving

svg.select('.x.axis')
    .transition()
    .duration(500)
    .attr({transform: 'translate(0,' + (config.height) + ')'})
    .call(xAxis);

before this line:

var transition = svg.transition().duration(750);

seems to work the way you intended: http://jsfiddle.net/Y274x/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM