单击时删除条形图的条形图

时间:2015-03-17 17:51:39

标签: javascript d3.js

我在d3.js中制作了一个条形图。我想要一种行为,点击任何一个条,该栏被删除。

我有一个函数,给定索引,删除数组元素并更新DOM。

首次点击工作正常,但在稍后点击后,我得到不同的索引值,其他一些栏被删除。知道为什么索引值在点击时不正确吗?

 <script>         

var dataSet = [ 
                    {key:0, value: 10},
                    {key:1, value: 18},
                    {key:2, value: 13},
                    {key:3, value: 19},
                    {key:4, value: 21},
                    {key:5, value: 25}                        
            ];

var canvasWidth = 500, canvasHeight = 500;

var svg = d3.select('body').append('svg').attr('width',canvasWidth).attr('height',canvasHeight);

svg.append('rect').attr('width', "100%").attr('height', '100%').attr('fill', 'lightgrey').classed('bg',true);    

// Bargraph

var barWidth = 20, padding = 1;
var barScale = d3.scale.linear()
                .domain([ d3.min(dataSet,function(data){return data.value}), d3.max(dataSet,function(data){return data.value}) ])
                .range ([ d3.min(dataSet,function(data){return data.value}), canvasHeight-padding])

// Create

var key = function(d) { return d.key; };

var barGraph = svg.selectAll('rect.bars').data(dataSet,key).enter().append('rect')
    .attr('x', function(data,index){return (padding+barWidth)*index})   
    .attr('y', function(data){ return canvasHeight-barScale(data.value); })        
    .attr('width', barWidth)
    .attr('height', function(data){ return barScale(data.value); })        
    .style('fill', 'teal')
    .classed('bars',true) 

    // ---------- Here is the problem --------------------

    .on('click',function(data,index){ console.log(index) ; removeElement(index) })
    .on('mouseover',function(data){ })

// Exit some

function removeElement(index) 
{
    dataSet.splice( index , 1)        
    var updated = svg.selectAll('rect.bars').data(dataSet,key)

    updated.exit()
    .transition()
    .duration(1000)
    .attr('width', 0) 
    .remove()
    .each('end',function()
    {
        svg.selectAll('rect.bars')
        .transition()
        .duration(1000)
        .attr('x', function(data,index){return (padding+barWidth)*index})   
    })
}

</script> 

2 个答案:

答案 0 :(得分:2)

可能是因为当您重新绑定数据(var updated = ...)时,删除的栏仍然是选择的一部分,这会影响索引。

我认为最好的解决方案是使用indexdataSet内查找dataSet.indexOf(data),而不是依赖于传递给点击处理程序的index。< / p>

或者,您可以尝试查看以下任何内容是否有效,如果您在<{strong> .each('end',...)处理程序中添加

  1. 再次重新绑定数据
  2. 在条形图上调用.order(),如svg.selectAll('rect.bars').order()
  3. 重新订阅点击事件,如svg.selectAll('rect.bars').on('click',...)

答案 1 :(得分:2)

我认为依靠索引和就地抛出d3数据绑定的就地数组拼接的组合。

尝试:

dataSet = dataSet.filter(function(d,i){
  return d.key != index;
});      
var updated = svg.selectAll('rect.bars').data(dataSet,key)

示例here

<强> EDITS

让我澄清一下,这不是抛出这种情况的拼接的原因,而是依靠指数转移的依赖性。无论删除元素,点击处理程序仍然认为数据是它的旧索引。您可以在console.log(index)中见证这一点。这就是我上面的代码有效的原因。您不再依赖索引删除,而是依赖d.key这是起始索引(点击记住的索引相同)。

解决此问题的另一种方法是使用splice,它是在数据更新时重新绑定事件处理程序。

function removeElement(index) 
{
    dataSet.splice(index, 1);
    var updated = svg.selectAll('rect.bars')
      .data(dataSet,key)
      .on('click',function(data,index){ console.log(index) ; removeElement(index) });

updated.exit()....

请参阅此example