cuixiping
cuixiping

Reputation: 25381

How to detect which segment of a svg path is clicked in javascript?

SVG path element for example:

<path id="path1" 
d="M 160 180 C 60 140 230 20 200 170 C 290 120 270 300 200 240 C 160 390 50 240 233 196" 
stroke="#009900" stroke-width="4" fill="none"/>

It has 4 svg segments (3 curve segments in human eyes):

    M 160 180 
    C 60 140 230 20 200 170 
    C 290 120 270 300 200 240 
    C 160 390 50 240 233 196

when click on the path, I get the x and y of mouse position, then how to detect which curve segment is clicked?

    function isInWhichSegment(pathElement,x,y){
        //var segs = pathElement.pathSegList; //all segments
        //
        //return the index of which segment is clicked
        //
    }

Upvotes: 5

Views: 1547

Answers (1)

Julien Gr&#233;goire
Julien Gr&#233;goire

Reputation: 17124

There are a few methods for SVGPathElements that you can use. Not really straighforward, but you could get the total length of your path, then check at every point of length the coordinates with getPointAtLength and compare it with coordinates of the click. Once you figure the click was at which length, you get the segment at that length with getPathSegAtLength. like that for example:

 var pathElement = document.getElementById('path1')
 var len = pathElement.getTotalLength();

 pathElement.onclick = function(e) {
   console.log('The index of the clicked segment is', isInWhichSegment(pathElement, e.offsetX, e.offsetY))
 }

 function isInWhichSegment(pathElement, x, y) {
   var seg;
   // You get get the coordinates at the length of the path, so you
   // check at all length point to see if it matches
   // the coordinates of the click
   for (var i = 0; i < len; i++) {
     var pt = pathElement.getPointAtLength(i);
     // you need to take into account the stroke width, hence the +- 2
     if ((pt.x < (x + 2) && pt.x > (x - 2)) && (pt.y > (y - 2) && pt.y < (y + 2))) {
       seg = pathElement.getPathSegAtLength(i);
       break;
     }
   }
   return seg;
 }
<svg>
  <path id="path1" d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="#009900" stroke-width="4" fill="none" />
</svg>

Upvotes: 1

Related Questions