Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recognize point(x,y) is inside svg path or outside

Tags:

javascript

svg

I have closed SVG path that is the province of the country.

How to recognize point(x,y) is inside SVG path or outside by javascript?

like image 923
Artin Falahi Avatar asked Dec 26 '13 17:12

Artin Falahi


People also ask

How does SVG define path?

A path is defined in SVG using the 'path' element. The basic shapes are all described in terms of what their equivalent path is, which is what their shape is as a path. (The equivalent path of a 'path' element is simply the path itself.)

What tag is used to define a path using SVG?

SVG Path - <path> The <path> element is used to define a path.

Can I add class to SVG path?

Just the same as you would add a class to an html element, by adding a class attribute. Though to be able to target that with css the svg code must be inserted into the document in-line, it can't be referenced by an <img> tag for example.


2 Answers

Call document.elementFromPoint. If the position is in the path then it will return that element. If the path is not filled then you may need to adjust the pointer-events property so that it works properly.

like image 114
Robert Longson Avatar answered Oct 19 '22 10:10

Robert Longson


For SVGGeometryElement, which includes paths and the basic shapes, there are

  • SVGGeometryElement.isPointInStroke() and
  • SVGGeometryElement.isPointInFill().

They return whether the given point is in the stroke respective in the fill, just as the name suggests.

Example:

const svg = document.getElementById("your-svg");
const path = document.getElementById("your-path");

// SVGPoint is deprecated according to MDN
let point = svg.createSVGPoint();
point.x = 40;
point.y = 32;

// or according to MDN
// let point = new DOMPoint(40, 32);

console.log("In stroke:", path.isPointInStroke(point)); // shows true
console.log("In fill:", path.isPointInFill(point)); // shows false
<svg id="your-svg" width="200" height="200">
  <path d="M 10 80 C 40 10, 65 10, 95 80 S 150 10, 150 110 S 80 190, 40 140 Z" stroke="yellowgreen" stroke-width="5" fill="#adff2f77" id="your-path"/>
  
  <!-- only to show where the point is -->
  <circle id="stroke-point" cx="40" cy="32" r="2.5" fill="red" />
</svg>

Besides being more descriptive than Document.elementFromPoint() those functions handle stacked elements and pointer events correctly. Note that the above example already contains the small circle laying over the path at the requested point. It is not or only hardly possible to check this case with Document.elementFromPoint().

const svg = document.getElementById("your-svg");
const path = document.getElementById("your-path");

console.log("In stroke / fill:", svg.ownerDocument.elementFromPoint(40, 32) == path);
<svg id="your-svg" width="200" height="200">
  <path d="M 10 80 C 40 10, 65 10, 95 80 S 150 10, 150 110 S 80 190, 40 140 Z" stroke="yellowgreen" stroke-width="5" fill="#adff2f77" id="your-path"/>
  
  <!-- only to show where the point is -->
  <circle id="stroke-point" cx="40" cy="32" r="2.5" fill="red" />
</svg>

Edit: Thanks to @Arlo who pointed out that the point representation object to use is not clear. MDN is using a DOMPoint (or DOMPointInit). Chrome assumed to get an SVGPoint which is deprecated according to MDN.

Note that the support on Edge and1 Internet Explorer is unknown at the moment (according to MDN).


1According to MDN Edge ≥79 supports both, isPointInStroke() and isPointInFill().

like image 27
miile7 Avatar answered Oct 19 '22 11:10

miile7