我有一个使用 D3 生成的散点图。图上的点(SVG 圆圈)可以通过单击它们来选择,并且可以使用 D3 画笔来选择区域。
为了确保圆圈获得点击事件,我需要先创建画笔,以便圆圈在其上方。不幸的是,这意味着当我的光标位于绘图中的某个点上时,我无法拖动以创建画笔范围。
有没有办法将悬停和单击事件传递给圆圈,但用画笔处理与拖动相关的事件?
我有一个使用 D3 生成的散点图。图上的点(SVG 圆圈)可以通过单击它们来选择,并且可以使用 D3 画笔来选择区域。
为了确保圆圈获得点击事件,我需要先创建画笔,以便圆圈在其上方。不幸的是,这意味着当我的光标位于绘图中的某个点上时,我无法拖动以创建画笔范围。
有没有办法将悬停和单击事件传递给圆圈,但用画笔处理与拖动相关的事件?
它可以通过使用 D3 画笔 API来完成(参见下面的注释)。
这是一个示例http://bl.ocks.org/4747894,其中:
brush
元素在圆圈后面mousedown
事件。(也可以响应其他事件。)brush
即使从其中一个圆圈内开始拖动,该元素也表现良好。一些跟踪和查看D3 源代码表明,当从画笔顶部的元素触发事件extent
时,没有正确重置。这可以通过在元素的侦听器中重置画笔来修复:mousemove
circle
extent
mousedown
circle
circles.on("mousedown", function (d, i) {
// _svg_ is the node on which the brush has been created
// x is the x-scale, y is the y-scale
var xy = d3.mouse(svg.node()),
xInv = x.invert(xy[0]),
yInv = y.invert(xy[1]);
// Reset brush's extent
brush.extent([[xInv, yInv], [xInv, yInv]]);
// Do other stuff which we wanted to do in this listener
});
注意: 根据 API,画笔的选择不会在调用时自动刷新.extent(values)
。仅单击一个圆圈将重置extent
但不会重绘所做的选择。circle
仅当在 内启动不同的选择,或通过单击圆圈和当前选择的外部时,才会丢弃选择。正如我从问题中所理解的那样,这是所需的行为。但是,这可能会破坏编写的代码,假设extent
画笔的任何内容都是图表上可见的选择。
使用selection.on
:http: //jsfiddle.net/NH6zD/1
var target,
dimensions = {width: 200, height: 200},
svg = d3.select("body").append("svg").attr(dimensions),
rect = svg.append("rect").attr(dimensions); // Must be beneath circles
svg
.on("mousedown", function() {
target = d3.event.target || d3.event.srcElement;
if ( target === rect.node() ) {
/* Brush */
} else {
/* Circle */
}
})
.on("mousemove", function() {
if (!target) return;
if ( target === svg.rect() ) {
/* Brush */
} else {
var mouse = d3.mouse(svg.node());
target.attr({x: mouse[0], y: mouse[1]});
}
});
(function(exit) {
for (var i in exit) svg.on(exit[i], function() { target = undefined; });
})(["mouseout", "mouseup"]);