[英]Adding an event listener to a d3 brush
I'm trying to figure out how to make the rectangle created by a d3 brush (the events rectangle, in particular), respond to a click event. 我试图弄清楚如何制作由d3画笔创建的矩形(特别是事件矩形),响应点击事件。 Eventually, I'd like to have a single click on this object bring up a menu, but I can't seem to get the rect element to catch the event.
最后,我想在这个对象上单击一下菜单,但我似乎无法获取rect元素来捕获事件。
I've tried the following code: 我试过以下代码:
var selector = d3.svg.brush();
var x = d3.scale.linear()
.range([0,500])
.domain([0,500]);
var y = d3.scale.linear()
.range([0,500])
.domain([0,500]);
d3.select('#myDiv')
.append('svg')
.attr('id','mySVG')
.attr('height',500)
.attr('width',500)
.call(selector.x(x).y(y).on('brushend',bindSelect))
function bindSelect(){
d3.select('#mySVG rect.extent')
.on('click',function(){alert('hi mom!')})
}
bindSelect
seems to fire just fine, and successfully select the .extent
rectangle, but I'm not getting any response on clicking the rectangle. bindSelect
似乎很好,并成功选择.extent
矩形,但我没有得到任何响应单击矩形。
The problem seems to be that d3 fires a brushend
event when the rectangle is clicked, which I'm guessing stops event propagation somewhere? 问题似乎是,当点击矩形时,d3会触发
brushend
事件,我猜这会阻止事件在某处传播?
Does anyone know how to get around this? 有谁知道怎么解决这个问题? My only thought is to create another rect on top of the extents rect on the
brushend
event, and then use that one to handle click behavior, but it seems like a messy way of doing things. 我唯一的想法是在
brushend
事件上的extents rect上创建另一个rect,然后使用那个来处理点击行为,但这似乎是一种混乱的做事方式。
Also, here is a fiddle of the code. 此外, 这里是代码的小提琴。
Getting the event you want might be a bit hairy and require changes to the D3 source code. 获得您想要的活动可能有点毛茸茸,需要更改D3源代码。 However, you can use the
brushend
event together with the methods provided for the brush to figure out whether somebody has clicked on the brush rectangle. 但是,您可以将
brushend
事件与为画笔提供的方法一起使用,以确定是否有人单击了画笔矩形。
var extent = selector.extent();
function bindSelect(){
if(!selector.empty() && !(extent < selector.extent() || extent > selector.extent())) {
console.log("foo");
}
extent = selector.extent();
}
The idea is that if the selection is not empty and the selected extent is the same as it was at the last brushend
event, then the user clicked on the selection instead of manipulating it. 我们的想法是,如果选择不为空且所选范围与上次
brushend
事件相同,则用户单击选择而不是操纵它。
This is a slightly improved version of Lars's answer, to handle two edge cases: 这是Lars答案的略微改进版本,用于处理两个边缘情况:
First, set up your brush like this: 首先,像这样设置你的画笔:
selector.x(x).y(y).on('brushstart', saveCursorPos)
.on('brushend', checkIfMoved))
Then, 然后,
var clickPos = [-1,-1];
function saveCursorPos() {
var e = d3.event.sourceEvent;
clickPos = [e.clientX,e.clientY];
}
function checkIfMoved() {
var e = d3.event.sourceEvent;
if(!selector.empty() && clickPos[0] === e.clientX && clickPos[1] === e.clientY) {
alert("foo");
}
}
The idea being to save the mouse position as opposed to the brush extent when you start dragging, and check if that has changed when the button is released. 当您开始拖动时,想法是保存鼠标位置而不是画笔范围,并在释放按钮时检查是否已更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.