[英]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',...)
:
.order()
on the bars, as in svg.selectAll('rect.bars').order()
.order()
在酒吧,在svg.selectAll('rect.bars').order()
svg.selectAll('rect.bars').on('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)
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()....
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.