2017-01-10 79 views
1

我正在研究基于用户选择更新/转换的d3.js水平条形图(http://bl.ocks.org/juan-cb/ab9a30d0e2ace0d2dc8c)。目前,我已经为图表添加了标签,但不再更新。不知道问题出在哪里。酒吧应该从左侧开始,但也出于某种原因向右移动。为了给条添加标签,我添加了“g”元素来保存矩形和文本。任何帮助将不胜感激。D3水平条形图不会转变为新数据集

的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

这里是我的建议:既然要追加两个矩形和文本元素到<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属性。

+0

非常感谢你为这个,对我帮助很大! – sparta93

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

为什么酒吧从顶部飞入,而不是从左到右?为什么bar.exit()。remove()使用这种方法? – user3359706