svg-path-intersections
v1.0.5
Published
Standalone library to get all intersections between 2 SVG paths
Downloads
9
Maintainers
Readme
svg-path-intersections
A standalone library to get intersections between two SVG paths. ~ 10KB minified/ 5KB gzipped.
It includes a path data parser compliant with the W3C SVGPathData interface draft and can handle all minified stringified path data inputs (especially A
commands with concatenated largeArc, sweep and final on-path parameters "bomb" quite a few other libraries).
Usage
You can either pass
- stringified path data
- a path data array
- a custom shape object using the
svgEl()
helper
let intersections = findPathIntersections(d1, d2)
or use it alongside with other path data parsers like Jarek Foksa's pathdata-polyfill and pass already parsed path data arrays to the findPathDataIntersections()
method.
let checkCollision = checkCollision(pathData1, pathData2) // returns true or false
Browser
<script src="https://cdn.jsdelivr.net/npm/svg-path-intersections@latest/js/svg-path-intersections_standalone.min.js"></script>
or
<script src="https://unpkg.com/svg-path-intersections@latest/js/svg-path-intersections_standalone.js"></script>
let d1 = 'M 75 0 a 1 1 45 010 100 1 1 45 010 -100'
let d2 = 'M 50 0 a 1 1 45 010 100 1 1 45 010 -100'
let intersections= findPathIntersections(d1, d2);
console.log(JSON.stringify(intersections, null, ' '));
Node
const pathIntersections = require('svg-path-intersections');
const {findPathIntersections, checkPathIntersection, findPathDataIntersections, pointAtT, parsePathDataNormalized} = pathIntersections;
let d1 = 'M 75 0 a 1 1 45 010 100 1 1 45 010 -100'
let d2 = 'M 50 0 a 1 1 45 010 100 1 1 45 010 -100'
let intersections= findPathIntersections(d1, d2);
console.log(JSON.stringify(intersections, null, ' '));
Parameters/Options
| Option | values/default | Effect |
|--|--|--|
| pathData1, pathData2 | path data input | accepts stringified pathdata or parsed arrays |
| stopAtFirst | false | stop search after first occurrence: helps to speed up processing e.g. for collision checks |
| quality | low, medium, high | default: "medium"; higher quality results in more accurate coordinates and t
values at the cost of longer processing times |
Methods
findPathIntersections(pathData1, pathData2, stopAtFirst, quality)
: finds all intersectionscheckCollision(d1, d2)
: stops at first intersection – faster than finding all occurencespointAtT(points, t)
: calculates point att
value for lines, quadratic or cubic béziers:- cubic bézier:
pointAtT([{x:0, y:0}, {x:0, y:0}, {x:0, y:0}, {x:0, y:0} ], 0.5)
(1. previous end point, 2. first control point, 3. second control point, 4. final on-path point) - quadratic bézier:
pointAtT([{x:0, y:0}, {x:0, y:0}, {x:0, y:0} ], 0.5)
(1. previous end point, 2. first control point, 3. final on-path point) - lineto
pointAtT([{x:0, y:0}, {x:0, y:0}], 0.5)
(1. previous end point, 2. final on-path point)
- cubic bézier:
parsePathDataNormalized(d, options)
Parse stringified pathdata to array with normalization options. See complete version with all options
Default options: toAbsolute, toLonghands, arcToCubics
Intersections between shapes via svgEl()
helper method
You can use this helper to add all svg geometry elements like so
let circle = svgEl(cx:10, cy:10, r: 10);
let ellipse = svgEl(cx:10, cy:10, rx: 10, ry:20 );
let path = svgEl(d: 'M 75 0 a 1 1 45 010 100 1 1 45 010 -100' );
// accepts an array of numbers or a string
let polygon = svgEl(points: '70 50 70 50 67.7 61.5 61.2 71.2 51.5 77.7 40 80 28.5 77.7 18.8 71.2 12.3 61.5 10 50 12.3 38.5 18.8 28.8 28.5 22.3 40 20 51.5 22.3 61.2 28.8 67.7 38.5' );
let polyline = svgEl(points: '70 50 70 50 67.7 61.5 61.2 71.2 51.5 77.7 40 80 28.5 77.7 18.8 71.2 12.3 61.5 10 50 12.3 38.5 18.8 28.8 28.5 22.3 40 20 51.5 22.3 61.2 28.8 67.7 38.5', type:'polyline' );
let rect = svgEl(x:10, y:10, width:50, height:50, rx:5, ry:3)
let line = svgEl(x1:10, y1:10, x2:50, y2:50)
// get intersections between shapes
let intersections = findPathIntersections(circle, path)
Intersections between DOM elements
let circle = document.querySelector('circle')
let path = document.querySelector('path')
let intersectionsDOM = getElementIntersections(circle, path)
Demos
Output
The returned intersection array contains:
- x/y coordinates for each intersection
t1
andt2
values for 1. and 2. path segments- segment indices (at which intersection occurred)
- segment command points (
cpts1
andcpts2
)
This way, you can calculate coordinates for both paths or split each path at t
values.
[
{
"x": 62.50000000097887,
"y": 98.40012176975786,
"t1": 0.15651097923256496,
"t2": 0.8434890204109524,
"segment1": 3,
"segment2": 2,
"cpts1": [
{
"x": 74.99999998680912,
"y": 100
},
{
"x": 47.410749986809115,
"y": 99.99999999272146
},
{
"x": 24.999999992721463,
"y": 77.5892499868091
},
{
"x": 25.000000000000014,
"y": 49.9999999868091
}
],
"cpts2": [
{
"x": 100,
"y": 50.000000013190885
},
{
"x": 99.99999999272146,
"y": 77.58925001319088
},
{
"x": 77.58924998680911,
"y": 100.00000000727853
},
{
"x": 49.999999986809115,
"y": 100
}
]
},
{
"x": 62.49999999505845,
"y": 1.5998782311929203,
"t1": 0.8434890203595754,
"t2": 0.15651097928396177,
"segment1": 4,
"segment2": 1,
"cpts1": [
{
"x": 25.000000000000014,
"y": 49.9999999868091
},
{
"x": 25.000000007278558,
"y": 22.41074998680911
},
{
"x": 47.410750013190906,
"y": -7.278536884314235e-9
},
{
"x": 75.0000000131909,
"y": 1.4210854715202004e-14
}
],
"cpts2": [
{
"x": 50,
"y": 0
},
{
"x": 77.58925001319088,
"y": 7.278543989741593e-9
},
{
"x": 100.00000000727853,
"y": 22.4107500131909
},
{
"x": 100,
"y": 50.000000013190885
}
]
}
]
Adjacent "touching" paths
Unlike other libraries path-intersections will also detect touching paths.
Related repositories
- svg-parse-path-normalized – Parse path data from string including fine-grained normalizing options
- svg-getpointatlength – calculate path length and point at paths on raw path data
Similar libraries
Credits
- Jarek Foksa for his great polyfill heavily inspring to adopt the new pathData interface methodology and for contributing to the specification
- Dmitry Baranovskiy for (raphael.j/snap.svg) pathToAbsolute/Relative functions
- Vitaly Puzrin (fontello) for the arc to cubic conversion method a2c.js and cubic to quadratic approximation
- Mike "POMAX" Kammermans for his great A Primer on Bézier Curves