简体   繁体   English

单击以删除条形图的条

[英]Removing bar graph's bars, on click

I have made a bar graph in d3.js. 我在d3.js中制作了条形图。 I want a behavior where on clicking on any of the bars, that bar gets deleted. 我想要一种行为,单击任何一个酒吧,该酒吧就会被删除。

I have a function which, given the index, deletes the array element and also updates the DOM. 我有一个函数,给定索引,它会删除数组元素并更新DOM。

First click works fine, but on later clicks, I am getting different index values and some other bar is getting deleted. 第一次单击可以正常工作,但是在以后的单击中,我得到的索引值不同,并且其他一些栏也被删除。 Any idea why the index value is not coming properly on click ? 知道为什么点击时索引值不正确吗?

 <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> 

Probably because when you rebind the data ( var updated = ... ) the removed bar is still part of the selection, which affects the index. 可能是因为当您重新绑定数据时( var updated = ... ),删除的条仍然是选择的一部分,这会影响索引。

I think the best solution would be to look up index within dataSet , using dataSet.indexOf(data) , instead of relying on the index that's passed into the click handler. 我认为最好的解决方案是使用dataSet.indexOf(data)dataSet查找index ,而不是依赖传递给单击处理程序的index

Alternatively, you can try to see if any of the following works, if you add it within the .each('end',...) handler: 另外,如果您 .each('end',...)处理函数中添加以下代码,则可以尝试查看以下任何一项是否.each('end',...)

  1. rebind the data yet again 重新绑定数据
  2. call .order() on the bars, as in svg.selectAll('rect.bars').order() 调用.order()在酒吧,在svg.selectAll('rect.bars').order()
  3. resubscribe to the click event, as in svg.selectAll('rect.bars').on('click',...) 重新订阅click事件,如svg.selectAll('rect.bars').on('click',...)

I think it's combination of relying on the index and the in-place array splice that's throwing d3 data-binding off. 我认为这是依赖于索引和就地数组拼接的结合,从而导致d3数据绑定失败。

Try: 尝试:

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

Example here . 这里的例子。

EDITS EDITS

Let me clarify, it's not the in-placeness of the splice that throwing this off, it's the reliance of shifting by index. 让我澄清一下,这不是拼接的适当性,而是依靠索引移动的依赖。 Regardless of removing the elements, the click handler still believes the data to be it's old index. 无论删除元素如何,单击处理程序仍然认为数据是它的旧索引。 You can witness this in your console.log(index) . 您可以在console.log(index)见证这一点。 This is why my code above works. 这就是上面我的代码起作用的原因。 You are no longer relying on removing by index, but by d.key which is the starting index (that same index the click is remembering). 您不再依赖于按索引删除,而是依靠d.key作为起始索引(单击所记住的那个索引)。

An alternate way to fix this that does work with splice is to re-bind your event handler on data update. 解决此问题的另一种有效方法是在数据更新上重新绑定事件处理程序。

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

See this example . 请参阅此示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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