Javascript D3水平条形图不会转换到新数据集

Javascript D3水平条形图不会转换到新数据集,javascript,d3.js,svg,Javascript,D3.js,Svg,我正在开发一个d3.js水平条形图(),它根据用户选择进行更新/转换。目前,我已将标签添加到图形中,但它不再更新。不知道问题出在哪里。酒吧应该从左侧开始,但由于某种原因也移到了右侧。为了给条添加标签,我添加了“g”元素来保存rect和文本。任何帮助都将不胜感激 JsFiddle- JS datasetTotal = [{ label: "Category 1", value: 19 }, { label: "Category 2", value: 5 }, {

我正在开发一个d3.js水平条形图(),它根据用户选择进行更新/转换。目前,我已将标签添加到图形中,但它不再更新。不知道问题出在哪里。酒吧应该从左侧开始,但由于某种原因也移到了右侧。为了给条添加标签,我添加了“g”元素来保存rect和文本。任何帮助都将不胜感激

JsFiddle-

JS

datasetTotal = [{
    label: "Category 1",
    value: 19
}, {
    label: "Category 2",
    value: 5
}, {
    label: "Category 3",
    value: 13
}, {
    label: "Category 4",
    value: 17
}, {
    label: "Category 5",
    value: 21
}, {
    label: "Category 6",
    value: 25
}];

datasetOption1 = [{
    label: "Category 1",
    value: 22
}, {
    label: "Category 2",
    value: 33
}, {
    label: "Category 3",
    value: 4
}, {
    label: "Category 4",
    value: 15
}, {
    label: "Category 5",
    value: 36
}, {
    label: "Category 6",
    value: 0
}];

datasetOption2 = [{
    label: "Category 1",
    value: 10
}, {
    label: "Category 2",
    value: 20
}, {
    label: "Category 3",
    value: 30
}, {
    label: "Category 4",
    value: 5
}, {
    label: "Category 5",
    value: 12
}, {
    label: "Category 6",
    value: 23
}];

d3.selectAll("input").on("change", selectDataset);

function selectDataset() {
    var value = this.value;
    if (value == "total") {
        change(datasetTotal);
    } else if (value == "option1") {
        change(datasetOption1);
    } else if (value == "option2") {
        change(datasetOption2);
    }
}

var margin = {
        top: (parseInt(d3.select('body').style('height'), 10) / 20),
        right: (parseInt(d3.select('body').style('width'), 10) / 20),
        bottom: (parseInt(d3.select('body').style('height'), 10) / 20),
        left: (parseInt(d3.select('body').style('width'), 10) / 5)
    },
    width = parseInt(d3.select('body').style('width'), 10) - margin.left - margin.right,
    height = parseInt(d3.select('body').style('height'), 10) - margin.top - margin.bottom;

var div = d3.select("body").append("div").attr("class", "toolTip");

var formatPercent = d3.format("");

var y = d3.scale.ordinal()
    .rangeRoundBands([height, 0], .2, 0.5);

var x = d3.scale.linear()
    .range([0, width]);

var xAxis = d3.svg.axis()
    .scale(x)
    .tickSize(-height)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");
//.tickFormat(formatPercent);

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

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

d3.select("input[value=\"total\"]").property("checked", true);
change(datasetTotal);

function change(dataset) {

    y.domain(dataset.map(function(d) {
        return d.label;
    }));
    x.domain([0, d3.max(dataset, function(d) {
        return d.value;
    })]);

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

    svg.select(".y.axis").remove();
    svg.select(".x.axis").remove();

    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .append("text")
        .attr("transform", "rotate(0)")
        .attr("x", 50)
        .attr("dx", ".1em")
        .style("text-anchor", "end")
        .text("Option %");


    var bar = svg.selectAll(".bar")
        .data(dataset, function(d) {
            return d.label;
        })
        // new data:
        .enter().append("g");

    bar.append("rect")
        .attr("class", "bar")
        .attr("x", function(d) {
            return x(d.value);
        })
        .attr("y", function(d) {
            return y(d.label);
        })
        .attr("width", function(d) {
            return width - x(d.value);
        })
        .attr("height", y.rangeBand());

    bar.append("text")
        .attr("x", function(d) {
            return x(d.value) - 3;
        })
        .attr("text-anchor", "end")
        .attr("y", function(d) {
            return y(d.label) + y.rangeBand() / 2;
        })
        .attr("dy", ".35em")
        .text(function(d) {
            return d.value;
        });


    var bars = d3.select("svg").selectAll("g.rects").data(dataset);

    // removed data:
    bars.exit().remove();

    // updated data:
    bars.transition()
        .duration(750)
        .attr("x", function(d) {
            return 0;
        })
        .attr("y", function(d) {
            return y(d.label);
        })
        .attr("width", function(d) {
            return x(d.value);
        })
        .attr("height", y.rangeBand());

};

以下是我的建议:由于您将矩形和文本元素添加到
(组)中,您的输入-更新-退出模式应该应用于组,而不是矩形和文本:

var bar = svg.selectAll(".bar")
    .data(dataset, function(d) {
        return d.label;
    });

var barExit = bar.exit().remove();

var barEnter = bar.enter()
    .append("g")
    .attr("class", "bar");
事实上,由于您的数据集总是有6个类别,您甚至不需要所有这些(代码可能会大大缩短)

这是你最新的小提琴:


PS我冒昧地让栅栏从左向右生长,而不是从右向左生长。如果这是不正确的,只需更改
x
width
属性。

我会对这种方法的优缺点感兴趣吗


为什么酒吧从顶部飞进来,而不是从左到右?为什么bar.exit().remove()不能使用这种方法?
bar = svg.selectAll(".bar")
              .data(dataset)

        bar_g = bar.enter()
              .append("g")
              .attr("class", "bar")
             .transition()
              .attr("transform", function (d) { return "translate(" + x(0) + "," + y(d.label) + ")"; });

        svg.selectAll(".bar")
             .append("rect")
             .attr("class", "rectband");

        svg.selectAll(".bar")
            .append("text")
            .attr("class", "textband");

        bar.selectAll(".textband")
          .attr("transform", function (d) { return "translate(" + x(d.value) + "," + 0 + ")"; })
          .attr("y", 30)
          .attr("dy", ".35em")
          .style("fill", "black")
          .text(function (d) { return d.value; });

        bar.selectAll(".rectband")
          .attr("width", function (d) { return x(d.value); })
          .attr("height", y.rangeBand());