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

时间:2017-01-10 02:12:48

标签: javascript d3.js svg

我正在使用d3.js水平条形图(http://bl.ocks.org/juan-cb/ab9a30d0e2ace0d2dc8c),根据用户选择更新/转换。目前,我已经向图表添加了标签,但它不再更新。不确定问题出在哪里。条形应从左侧开始,但由于某种原因也向右移动。为了向酒吧添加标签,我添加了#34; g"用于保存矩形和文本的元素。任何帮助将不胜感激。

JsFiddle - https://jsfiddle.net/fewpwqhd/1/

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());

};

2 个答案:

答案 0 :(得分:2)

以下是我的建议:由于您要将矩形和文本元素附加到<g>(组),因此您的输入更新退出模式应该应用于组,而不是矩形和文本:

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个类别,您甚至不需要所有这些(代码可能会大大缩短)。

这是您更新的小提琴:https://jsfiddle.net/2523onr3/

PS 我冒昧地让酒吧从从左到右,而不是从右到左。如果这不正确,只需更改xwidth属性。

答案 1 :(得分:1)

我对这种方法的利弊感兴趣吗?

https://jsfiddle.net/sjp700/2523onr3/2/

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());