score:1

I ended up using the method in SVGEdit suggested by DuoPixel. It uses other SVGEdit method defined in svgcanvas.js so it's not really meant as a standalone. Here's a working link to DuoPixel method suggested in the comments: https://github.com/duopixel/Method-Draw/blob/master/method-draw/src/svgcanvas.js#L600

With the specific implementation in case the link changes:

// 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;
};

score:10

Preface: @Duopixel's comment on your original post is great -- I didn't know that method exists. However, it looks like it only supports a rectangular region per the MSDN docs, whereas it seems more intuitive to have a circle around the mouse.

A couple of other techniques:

  1. Use an invisible, thick stroke that "expands" your element, if you're not otherwise using the stroke for styling, or draw a transparent line/shape on top of the element that is some amount larger. Listen to the 'click' event for these elements.

  2. Do a pairwise comparison of every element with that of the mouse's click radius. I made an example here: http://jsfiddle.net/AkPN2/5/. I only implemented circles because they were easy -- you'd need to add the geometry for rectangles.


Related Query