8

我正在使用 D3 JavaScript 库来构建 SVG 图并将鼠标事件分配给它们。SVG 图可能很复杂,由许多任意路径元素组成。我一直在努力寻找一种方法来确定鼠标悬停事件中所有附近的元素。因此,例如,当鼠标光标移动到图表上时,我可以确定距离光标 N 个像素半径内的所有组件 SVG 元素。

我完全不知道如何解决这个问题。我什至不确定是否有允许我确定 SVG 组成元素是否在边界区域内的 API?

任何有关如何解决此问题的提示将不胜感激。

4

2 回答 2

10

前言:@Duopixel 对您的原始帖子的评论很棒——我不知道这种方法存在。但是,看起来它只支持 MSDN 文档中的矩形区域,而在鼠标周围有一个圆圈似乎更直观。

其他一些技术:

  1. 如果您没有以其他方式使用笔触进行样式设置,请使用不可见的粗笔触来“扩展”您的元素,或者在元素顶部绘制一条更大的透明线条/形状。监听这些元素的“点击”事件。

  2. 将每个元素与鼠标点击半径进行成对比较。我在这里做了一个例子:http: //jsfiddle.net/AkPN2/5/。我只实现了圆形,因为它们很简单——您需要为矩形添加几何图形。

于 2012-09-30T03:41:04.843 回答
1

我最终使用了 DuoPixel 建议的 SVGEdit 中的方法。它使用 svgcanvas.js 中定义的其他 SVGEdit 方法,因此它并不是真正意义上的独立。这是评论中建议的 DuoPixel 方法的工作链接: https ://github.com/duopixel/Method-Draw/blob/master/method-draw/src/svgcanvas.js#L600

如果链接发生变化,具体实现如下:

// This method sends back an array or a NodeList full of elements that
// intersect the multi-select rubber-band-box on the current_layer only.
//
// Since the only browser that supports the SVG DOM getIntersectionList is Opera,
// we need to provide an implementation here. We brute-force it for now.
//
// Reference:
// Firefox does not implement getIntersectionList(), see https://bugzilla.mozilla.org/show_bug.cgi?id=501421
// Webkit does not implement getIntersectionList(), see https://bugs.webkit.org/show_bug.cgi?id=11274
var getIntersectionList = this.getIntersectionList = function(rect) {
if (rubberBox == null) { return null; }
var parent = current_group || getCurrentDrawing().getCurrentLayer();
if(!curBBoxes.length) {
// Cache all bboxes
curBBoxes = getVisibleElementsAndBBoxes(parent);
}
var resultList = null;
try {
resultList = parent.getIntersectionList(rect, null);
} catch(e) { }
if (resultList == null || typeof(resultList.item) != "function") {
resultList = [];
if(!rect) {
var rubberBBox = rubberBox.getBBox();
var bb = {};
for(var o in rubberBBox) {
bb[o] = rubberBBox[o] / current_zoom;
}
rubberBBox = bb;
} else {
var rubberBBox = rect;
}
var i = curBBoxes.length;
while (i--) {
if(!rubberBBox.width || !rubberBBox.width) continue;
if (svgedit.math.rectsIntersect(rubberBBox, curBBoxes[i].bbox)) {
resultList.push(curBBoxes[i].elem);
}
}
}
// addToSelection expects an array, but it's ok to pass a NodeList
// because using square-bracket notation is allowed:
// http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html
return resultList;
};
于 2014-09-05T15:30:59.523 回答