问题
Does a Javascript library exist which can perform boolean operations on paths (bezier curves)?
I know about Paper.js and Raphael.js, but both cannot perform these actions now.
回答1:
Paper.js now has boolean operations in its core:
https://github.com/paperjs/paper.js/blob/master/src/path/PathItem.Boolean.js
And here you can see the operations in action:
http://assets.paperjs.org/boolean/
回答2:
If you convert path to polygons (eg. using pathelement.getPointAtLength()), then you can use Javascript Clipper, which is a javascript port of popular Angus Johnson's Clipper Library.
This is an example of Difference, but also Union, Intersect and Xor are possible:
The page of Javascript Clipper is here.
If getPointAtLength() gives too much points, Javascript Clipper has a function ClipperLib.Lighten(), which can reduce point count significantly.
The library supports also polygon offsetting. See the live demo.
EDIT: after testing I can confirm that pathelement.getPointAtLength() is best suitable for eg. hit testing, but not so good for polygonizing in this case, because it produces too few or too much points and doesn't take into account the curvature. It's the fact that tight curves need more points and loose curves fewer. Better is to convert all path segments to Cubic curves and use some adaptive algorithm for polygonizing curves. I have made some tests and may be soon can introduce a better way for polygonizing.
EDIT: I have managed to implement SVG path polygonizing function, which handles all kind of paths and also flattens transformations. After testing thousands randomly generated paths and transformations it seems to be reliable. Also all possible degenerate cases (where curves are collinear or some of the points are the same) are handled without issues. Although it is already many times faster and more precise than native getPointAtLength() while producing significantly fewer points, the process has room for speed improvements using eg. taxicab angles instead of atan2() and making the code fully Web Workers compatible by removing all DOM methods. I want to make it 100% bugfree before publishing it. It's ideal use case is eg. possibility to make boolean operations with generated polygons.
回答3:
Try to use this - https://github.com/interstateone/polygons
回答4:
There's a plugin for raphael.js providing this functionality – https://github.com/poilu/raphael-boolean
回答5:
Example of PaperJS boolean operations with intersect function
We can do it with PaperJS boolean operations, which can operate with SVG paths (bezier curves paths inclusive).
PaperJS has 5 different boolean operations: exclude
, subtract
, unite
, intersect
, divide
. You can see all this examples here.
This operations are also functions with the same name and they return item
object, which has the function exportSVG(). It returns true SVG Path element
, which has a new shape of both paths intersection. It is very useful – you can get the value for the path attribute d
or you can append this path element to your new SVG element.
paper.install(window);
window.onload = function()
{
paper.setup('canvas');
var p1 = 'M 24.379464,51.504463 23.434524,23.156249 38.742559,12.572916 c 0,0 29.860118,-9.0714281 17.00893,0.755953 -12.851191,9.82738 13.229166,19.465774 13.229166,19.465774 z',
p2 = 'm 32.883928,0.28869028 c 0,0 -15.686011,1.51190452 -8.504463,7.18154712 7.181546,5.6696426 50.270836,30.0491076 26.458332,42.3333336 -23.8125,12.284226 47.058036,14.174107 47.058036,14.174107 z',
path1 = new Path(p1),
path2 = new Path(p2);
path1.fillColor = 'rgba(255,0,0,.5)';
path1.position = new Point(25, 25);
path2.fillColor = 'rgba(0,255,0,.5)';
path2.position = new Point(40, 25);
var result = path2.intersect(path1);
result.selected = true;
result.fillColor = '#77f';
//exportSVG() docu: http://paperjs.org/reference/item/#exportsvg
var svgPathElement = result.exportSVG(),
dPath = svgPathElement.getAttribute('d');
document.querySelector('path').setAttribute('d', dPath);
var output = document.querySelector('#output');
output.innerHTML = '<pre><b>D value from path:</b> ' + dPath + '</pre>';
output.innerHTML += '<xmp>HTML string of path: ' + svgPathElement.outerHTML + '</xmp>';
};
table
{
margin-left:14px;
padding-left:14px;
border-left:1px solid gray;
display:inline-block
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.0/paper-full.min.js"></script>
<canvas id="canvas" width="75" height="75" resize></canvas>
<table><tr><td><b>Our new shape of both paths intersection in separate SVG:</b></td></tr>
<tr><td>
<svg width="75" height="75" viewBox="0 0 75 75">
<path fill="rgba(0,0,255,.5)" d=""/>
</svg>
</td></tr></table>
<div id="output"></div>
Useful links:
- PaperJS examples
- PaperJS Reference (documentation)
来源:https://stackoverflow.com/questions/11880739/which-javascript-library-can-do-boolean-operations-with-bezier-curves