https://github.com/nfroidure/svg-pathdata
Parse SVG PathDatas
https://github.com/nfroidure/svg-pathdata
javascript svg svg-path
Last synced: 6 months ago
JSON representation
Parse SVG PathDatas
- Host: GitHub
- URL: https://github.com/nfroidure/svg-pathdata
- Owner: nfroidure
- License: mit
- Created: 2013-11-02T19:35:50.000Z (over 12 years ago)
- Default Branch: main
- Last Pushed: 2025-03-27T09:13:13.000Z (about 1 year ago)
- Last Synced: 2025-03-30T19:36:46.460Z (about 1 year ago)
- Topics: javascript, svg, svg-path
- Language: TypeScript
- Size: 1.06 MB
- Stars: 193
- Watchers: 8
- Forks: 19
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: .github/CONTRIBUTING
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
[//]: # ( )
[//]: # (This file is automatically generated by a `metapak`)
[//]: # (module. Do not change it except between the)
[//]: # (`content:start/end` flags, your changes would)
[//]: # (be overridden.)
[//]: # ( )
# svg-pathdata
> Manipulate SVG path data (path[d] attribute content) simply and efficiently.
[](https://github.com/nfroidure/svg-pathdata/blob/main/LICENSE)
[](https://coveralls.io/github/nfroidure/svg-pathdata?branch=main)
[//]: # (::contents:start)
## Usage
Install the module:
```sh
npm install --save svg-pathdata
```
Then in your JavaScript files:
```js
import {
SVGPathData,
SVGPathDataTransformer,
SVGPathDataEncoder,
SVGPathDataParser,
} from 'svg-pathdata';
```
## Reading PathData
```js
const pathData = new SVGPathData(`
M 10 10
H 60
V 60
L 10 60
Z`);
console.log(pathData.commands);
// [ {type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10},
// {type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60},
// {type: SVGPathData.VERT_LINE_TO, relative: false, y: 60},
// {type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60},
// {type: SVGPathData.CLOSE_PATH}]
```
## Reading PathData in chunks
```js
const parser = new SVGPathDataParser();
parser.parse(' '); // returns []
parser.parse('M 10'); // returns []
parser.parse(' 10'); // returns [{type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10 }]
parser.write('H 60'); // returns [{type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60 }]
parser.write('V'); // returns []
parser.write('60'); // returns [{type: SVGPathData.VERT_LINE_TO, relative: false, y: 60 }]
parser.write('L 10 60 \n Z');
// returns [
// {type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60 },
// {type: SVGPathData.CLOSE_PATH }]
parser.finish(); // tell parser there is no more data: will throw if there are unfinished commands.
```
## Outputting PathData
```js
const pathData = new SVGPathData(`
M 10 10
H 60
V 60
L 10 60
Z`);
// returns "M10 10H60V60L10 60Z"
encodeSVGPath({ type: SVGPathData.MOVE_TO, relative: false, x: 10, y: 10 });
// returns "M10 10"
encodeSVGPath({ type: SVGPathData.HORIZ_LINE_TO, relative: false, x: 60 });
// returns "H60"
encodeSVGPath([
{ type: SVGPathData.VERT_LINE_TO, relative: false, y: 60 },
{ type: SVGPathData.LINE_TO, relative: false, x: 10, y: 60 },
{ type: SVGPathData.CLOSE_PATH },
]);
// returns "V60L10 60Z"
```
## Transforming PathData
This library can perform transformations on SVG paths. Here is
[an example of that kind of use](https://github.com/nfroidure/svgicons2svgfont/blob/aa6df0211419e9d61c417c63bcc353f0cb2ea0c8/src/index.js#L192).
### Transforming entire paths
```js
new SVGPathData(`
m 10,10
h 60
v 60
l 10,60
z`)
.toAbs()
.encode();
// return s"M10,10 H70 V70 L80,130 Z"
```
### Transforming partial data
Here, we take SVGPathData from stdin and output it transformed to stdout.
```js
const transformingParser = new SVGPathDataParser().toAbs().scale(2, 2);
transformingParser.parse('m 0 0'); // returns [{ type: SVGPathData.MOVE_TO, relative: false, x: 0, y: 0 }]
transformingParser.parse('l 2 3'); // returns [{ type: SVGPathData.LINE_TO, relative: false, x: 4, y: 6 }]
```
## Supported transformations
You can find all supported transformations in
[src/SVGPathDataTransformer.ts](https://github.com/nfroidure/SVGPathData/blob/master/src/SVGPathDataTransformer.ts#L47).
Additionally, you can create your own by writing a function with the following
signature:
```js
type TransformFunction = (command: SVGCommand) => SVGCommand | SVGCommand[];
function SET_X_TO(xValue = 10) {
return function(command) {
command.x = xValue; // transform command objects and return them
return command;
};
};
// Synchronous usage
new SVGPathData('...')
.transform(SET_X_TO(25))
.encode();
// Chunk usage
new SVGPathDataParser().transform(SET_X_TO(25));
```
## Contributing
Clone this project, run:
```sh
npm install; npm test
```
[//]: # (::contents:end)
# API
## Functions
- annotateArcCommand()
-
https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
Fixes rX and rY.
Ensures lArcFlag and sweepFlag are 0 or 1
Adds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)
Adds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 < phi2 iff. c.sweepFlag == true - intersectionUnitCircleLine()
-
Solves a quadratic system of equations of the form
a * x + b * y = c
x² + y² = 1
This can be understood as the intersection of the unit circle with a line.
=> y = (c - a x) / b
=> x² + (c - a x)² / b² = 1
=> x² b² + c² - 2 c a x + a² x² = b²
=> (a² + b²) x² - 2 a c x + (c² - b²) = 0 -
arePointsCollinear(p1, p2, p3) ⇒ -
Determines if three points are collinear (lie on the same straight line)
and the middle point is on the line segment between the first and third points - createEllipse()
-
Creates an ellipse path centered at (cx,cy) with radii rx and ry
- createRect()
-
Creates a rectangle path with optional rounded corners
- createPolyline()
-
Creates a polyline from an array of coordinates [x1,y1,x2,y2,...]
- createPolygon()
-
Creates a closed polygon from an array of coordinates
-
REMOVE_COLLINEAR(commands) ⇒ -
Process a path and remove collinear points
-
REVERSE_PATH(commands, preserveSubpathOrder) ⇒ -
Reverses the order of path commands to go from end to start
IMPORTANT: This function expects absolute commands as input.
It doesn't convert relative to absolute - use SVGPathDataTransformer.TO_ABS() first if needed.
## annotateArcCommand()
https://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
Fixes rX and rY.
Ensures lArcFlag and sweepFlag are 0 or 1
Adds center coordinates: command.cX, command.cY (relative or absolute, depending on command.relative)
Adds start and end arc parameters (in degrees): command.phi1, command.phi2; phi1 < phi2 iff. c.sweepFlag == true
## intersectionUnitCircleLine()
Solves a quadratic system of equations of the form
a * x + b * y = c
x² + y² = 1
This can be understood as the intersection of the unit circle with a line.
=> y = (c - a x) / b
=> x² + (c - a x)² / b² = 1
=> x² b² + c² - 2 c a x + a² x² = b²
=> (a² + b²) x² - 2 a c x + (c² - b²) = 0
## arePointsCollinear(p1, p2, p3) ⇒
Determines if three points are collinear (lie on the same straight line)
and the middle point is on the line segment between the first and third points
**Kind**: global function
**Returns**: true if the points are collinear and p2 is on the segment p1-p3
| Param | Description |
| --- | --- |
| p1 | First point [x, y] |
| p2 | Middle point that might be removed |
| p3 | Last point [x, y] |
## createEllipse()
Creates an ellipse path centered at (cx,cy) with radii rx and ry
## createRect()
Creates a rectangle path with optional rounded corners
## createPolyline()
Creates a polyline from an array of coordinates [x1,y1,x2,y2,...]
## createPolygon()
Creates a closed polygon from an array of coordinates
## REMOVE\_COLLINEAR(commands) ⇒
Process a path and remove collinear points
**Kind**: global function
**Returns**: New array with collinear points removed
| Param | Description |
| --- | --- |
| commands | Array of SVG path commands to process (must be absolute) |
## REVERSE\_PATH(commands, preserveSubpathOrder) ⇒
Reverses the order of path commands to go from end to start
IMPORTANT: This function expects absolute commands as input.
It doesn't convert relative to absolute - use SVGPathDataTransformer.TO_ABS() first if needed.
**Kind**: global function
**Returns**: New SVG commands in reverse order with absolute coordinates
| Param | Description |
| --- | --- |
| commands | SVG path commands in absolute form to reverse |
| preserveSubpathOrder | If true, keeps subpaths in their original order |
# Authors
- [Nicolas Froidure](https://insertafter.com/en/index.html)
- [Anders Kaseorg](mailto:andersk@mit.edu)
# License
[MIT](https://github.com/nfroidure/svg-pathdata/blob/main/LICENSE)