How to identify neighboring SVG elements on a mouse event?

I use the D3 JavaScript library to build an SVG diagram and assign them mouse events. An SVG diagram can be complex, with many arbitrary path elements. I'm struggling to determine a way to detect all nearby elements in a mouseover event. So, for example, when the mouse cursor moves along the diagram, I can determine all the elements of the SVG component within a radius of N pixels from the cursor.

I am completely fixated on how to handle this. I'm not even sure if there is an API that allows me to determine if an SVG element is within the bounding area?

Any hints on how to handle this would be most appreciated.

+8
svg
source share
2 answers

Foreword: @Duopixel's comment on your original post is great - I did not know that this method exists. However, it seems that it only supports a rectangular area for MSDN documents, while it seems more intuitive to have a circle around the mouse.

A few other methods:

  • Use an invisible, thick stroke that β€œexpands” your element unless you otherwise use the stroke for styling, or draw a transparent line / shape on top of the element, which is slightly larger. Listen for the 'click' event for these elements.

  • Make a pairwise comparison of each element with the radius of the mouse click. I gave an example here: http://jsfiddle.net/AkPN2/5/ . I just implemented circles because they were light - you had to add geometry for the rectangles.

+10
source share

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

In a specific implementation, if 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 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; }; 
+1
source share

All Articles