The browsers which have implemented parts of the SVG spec (Firefox etc) do hit-testing for us for free - if I attach a mousedown listener on an SVG object, I get notified whenever the shape is clicked. This is amazing, especially for complex polygon shapes.
I'm wondering if there's a way I can utilize this feature for a bit more hit testing. I want to know if a given rectangle intersects any of my SVG shapes.
For example, I add 3 complex polygons to my element. Now I want to know if rectangle (40, 40, 100, 100) intersects any of them. Does anyone have an idea how I could possibly hook into the already great hit-testing support available, instead of adding all this code myself?
The SVG 1.1 DOM has just the right method (unfortunately it's not yet implemented in mozilla):
var nodelist = svgroot.getIntersectionList(hitrect, null);
For a full working example see here.
Chrome's version of checkIntersection (and getIntersectionList) tests the element bounding boxes, rather than the elements themselves. I was able to write my own checkIntersection which works on chrome by using a canvas with this fairly involved approach which seems to work well for small rectangles and will be slow for large ones, so it's nice for hit testing. This technique will work as a polyfill for checkIntersection in Chrome, for small rectangles and possibly other browsers that have broken implementations of checkIntersection.
To test if a rectangle intersects with any of your shapes, do this:
getIntersectionList works fine in Opera. My problem is that the functions in the SVG 1.1 Full spec regarding this requires that elements must be rendered (and possible target for pointer events) in order to be detected as hit. Unfortunately this makes these functions useless for hit testing in a game world where only part of the world is currently visible.
I don't know of any way of intersecting a whole rectangle. But you can intersect a point, so you could build a more complicated check out of that:
var el= document.elementFromPoint(x, y);
will give you the highest-stacked element at a particular page-relative co-ordinate. You'll get the
<svg> element if no shapes inside the SVG are hit.
This is a non-standard Mozilla extension, but it works on WebKit as well. Unfortunately, though it exists in Opera, it won't look inside
<svg>, so on that browser the element will always be the SVGSVGElement.
©2020 All rights reserved.