├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── lib └── svg-path-generator.js ├── package.json └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Matthew Conlen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # svg path generator 3 | 4 | ## utilities to generate svg paths 5 | 6 | ## installation 7 | 8 | use with node or in browser with browserify 9 | 10 | ``` 11 | npm install svg-path-generator 12 | ``` 13 | 14 | ## usage 15 | 16 | ```js 17 | var Path = require('svg-path-generator'); 18 | 19 | var path = Path() 20 | .moveTo(10, 25) 21 | .lineTo(10, 75) 22 | .lineTo(60, 75) 23 | .lineTo(10, 25) 24 | .end(); 25 | 26 | console.log(path) // M 10 25 L 10 75 L 60 75 L 10 25 27 | 28 | ``` 29 | 30 | to use relative coordinates, call `.relative()` before any method 31 | 32 | e.g. 33 | ```js 34 | var Path = require('svg-path-generator'); 35 | 36 | var path = Path() 37 | .moveTo(10, 25) 38 | .relative().lineTo(0, 50) 39 | .relative().lineTo(50, 0) 40 | .relative().lineTo(-50, -50) 41 | .end(); 42 | 43 | console.log(path) // M 10 25 l 0 50 l 50 0 l -50 -50 44 | 45 | ``` 46 | 47 | both paths are equivalent. 48 | 49 | 50 | 51 | ## methods 52 | 53 | ### svg path methods 54 | 55 | * `moveTo(x, y)` 56 | * moves current position to x,y without drawing anything 57 | * multiple sets of coordinates can be provided, i.e. `Path.moveTo(x1, y1, x2, y2)` is equivalent to `Path.moveTo(x1, y1).moveTo(x2, y2)` 58 | * `lineTo(x, y)` 59 | * moves current position to x,y while drawing a line from previous position 60 | * multiple sets of coordinates can be provided 61 | * `horizontalLineTo(x)` 62 | * move from previous position along the x axis, drawing a line 63 | * `verticalLineTo(y)` 64 | * move from previous position along the y axis, drawing a line 65 | * `curveTo(x1, y1, x2, y2, x, y)` 66 | * Draws a cubic Bézier curve from the current point to (x,y) using (x1,y1) as the control point at the beginning of the curve and (x2,y2) as the control point at the end of the curve. 67 | * multiple sets of coordinates can be provided 68 | 69 | * `smoothCurveTo(x2, y2, x, y)` 70 | * Draws a cubic Bézier curve from the current point to (x,y). The first control point is assumed to be the reflection of the second control point on the previous command relative to the current point. 71 | * multiple sets of coordinates can be provided 72 | 73 | * `bezierCurveTo(x1, y1, x, y)` 74 | * Draws a quadratic Bézier curve from the current point to (x,y) using (x1,y1) as the control point. 75 | * multiple sets of coordinates can be provided 76 | 77 | * `smoothBezierCurveTo(x, y)` 78 | * Draws a quadratic Bézier curve from the current point to (x,y). The control point is assumed to be the reflection of the control point on the previous command relative to the current point. 79 | * multiple sets of coordinates can be provided 80 | 81 | * `ellipticalArc(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y)` 82 | * Draws an elliptical arc from the current point to (x, y). The size and orientation of the ellipse are defined by two radii (rx, ry) and an x-axis-rotation, which indicates how the ellipse as a whole is rotated relative to the current coordinate system. The center (cx, cy) of the ellipse is calculated automatically to satisfy the constraints imposed by the other parameters. large-arc-flag and sweep-flag contribute to the automatic calculations and help determine how the arc is drawn. 83 | 84 | * `close()` 85 | * closes the current path 86 | 87 | ### other methods 88 | 89 | * `.relative()` call before any method to have the method accept relative instead of absolute coordinates 90 | * `.end()` converts the Path object to a string. This also gets called on the `.toString()` method 91 | 92 | 93 | ## license 94 | 95 | MIT 96 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = require('./lib/svg-path-generator'); 3 | 4 | -------------------------------------------------------------------------------- /lib/svg-path-generator.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function SvgPathGenerator(path) { 4 | if (!(this instanceof SvgPathGenerator)) { 5 | return new SvgPathGenerator(path); 6 | } 7 | 8 | this.currentPath = (path || '') + ' '; 9 | this.isRelative = false; 10 | } 11 | 12 | 13 | module.exports = SvgPathGenerator; 14 | 15 | 16 | 17 | SvgPathGenerator.prototype.toString = function() { 18 | return this.end(); 19 | }; 20 | 21 | 22 | SvgPathGenerator.prototype.moveTo = function() { 23 | this._appendData('M', arguments); 24 | return this; 25 | }; 26 | 27 | 28 | SvgPathGenerator.prototype.close = SvgPathGenerator.prototype.closePath = function() { 29 | this._appendData('Z', []); 30 | return this; 31 | }; 32 | 33 | SvgPathGenerator.prototype.lineTo = function() { 34 | this._appendData('L', arguments); 35 | return this; 36 | }; 37 | 38 | SvgPathGenerator.prototype.horizontalLineTo = function(x) { 39 | this._appendData('H', [x]); 40 | return this; 41 | }; 42 | 43 | SvgPathGenerator.prototype.verticalLineTo = function(y) { 44 | this._appendData('V', [y]); 45 | return this; 46 | }; 47 | 48 | SvgPathGenerator.prototype.curveTo = function() { 49 | this._appendData('C', arguments); 50 | return this; 51 | }; 52 | 53 | SvgPathGenerator.prototype.smoothCurveTo = function() { 54 | this._appendData('S', arguments); 55 | return this; 56 | }; 57 | 58 | SvgPathGenerator.prototype.bezierCurveTo = function() { 59 | this._appendData('Q', arguments); 60 | return this; 61 | }; 62 | 63 | SvgPathGenerator.prototype.smoothBezierCurveTo = function() { 64 | this._appendData('T', arguments); 65 | return this; 66 | }; 67 | 68 | SvgPathGenerator.prototype.ellipticalArc = function() { 69 | this._appendData('A', arguments); 70 | return this; 71 | }; 72 | 73 | 74 | SvgPathGenerator.prototype.relative = function() { 75 | this.isRelative = true; 76 | return this; 77 | }; 78 | 79 | SvgPathGenerator.prototype.end = function() { 80 | return this.currentPath.trim(); 81 | }; 82 | 83 | 84 | SvgPathGenerator.prototype._appendData = function(symbol, args) { 85 | 86 | args = Array.prototype.slice.call(args); 87 | 88 | if(this.isRelative) { 89 | symbol = symbol.toLowerCase(); 90 | this.isRelative = false; 91 | } 92 | 93 | this.currentPath += symbol + ' ' + args.join(' ') + ' '; 94 | }; 95 | 96 | 97 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svg-path-generator", 3 | "version": "1.1.0", 4 | "description": "Easily generate svg path strings", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "http://github.com/mathisonian/svg-path-generator" 12 | }, 13 | "keywords": [ 14 | "svg", 15 | "path", 16 | "svg-path", 17 | "svg-path-generator" 18 | ], 19 | "author": "Matthew Conlen", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/mathisonian/svg-path-generator/issues" 23 | }, 24 | "homepage": "https://github.com/mathisonian/svg-path-generator", 25 | "devDependencies": { 26 | "expect.js": "^0.3.1", 27 | "mocha": "^2.0.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 2 | var expect = require('expect.js'); 3 | var Path = require('..'); 4 | 5 | 6 | describe('svg-path-generator tests', function() { 7 | 8 | it('should draw a triangle', function() { 9 | var path = Path() 10 | .moveTo(10, 25) 11 | .lineTo(10, 75) 12 | .lineTo(60, 75) 13 | .lineTo(10, 25) 14 | .end(); 15 | 16 | expect(path).to.be('M 10 25 L 10 75 L 60 75 L 10 25'); 17 | }); 18 | 19 | 20 | it('should draw a triangle with a relative lineTo', function() { 21 | var path = Path() 22 | .moveTo(10, 25) 23 | .lineTo(10, 75) 24 | .lineTo(60, 75) 25 | .relative() 26 | .lineTo(-50, -50) 27 | .end(); 28 | 29 | expect(path).to.be('M 10 25 L 10 75 L 60 75 l -50 -50'); 30 | }); 31 | 32 | 33 | it('should draw a line with multiple input pairs', function() { 34 | var path = Path() 35 | .moveTo(10, 25) 36 | .lineTo(10, 75, 60, 75, 10, 25) 37 | .end(); 38 | 39 | expect(path).to.be('M 10 25 L 10 75 60 75 10 25'); 40 | }); 41 | 42 | 43 | it('should convert Path object to string with toString', function() { 44 | var path = Path() 45 | .moveTo(10, 25) 46 | .lineTo(10, 75, 60, 75, 10, 25); 47 | 48 | expect(path.toString()).to.be('M 10 25 L 10 75 60 75 10 25'); 49 | }); 50 | 51 | 52 | it('should work with an initial path', function() { 53 | var path = Path('M 10 25') 54 | .lineTo(10, 75, 60, 75, 10, 25) 55 | .end(); 56 | 57 | expect(path).to.be('M 10 25 L 10 75 60 75 10 25'); 58 | }); 59 | 60 | 61 | 62 | it('should work with a closed path', function() { 63 | var path1 = Path() 64 | .moveTo(10, 25) 65 | .lineTo(10, 75) 66 | .lineTo(60, 75) 67 | .relative() 68 | .lineTo(-50, -50) 69 | .close() 70 | .end(); 71 | 72 | var path2 = Path() 73 | .moveTo(10, 25) 74 | .lineTo(10, 75) 75 | .lineTo(60, 75) 76 | .relative() 77 | .lineTo(-50, -50) 78 | .closePath() 79 | .end(); 80 | 81 | expect(path1).to.be(path2); 82 | 83 | expect(path1).to.be('M 10 25 L 10 75 L 60 75 l -50 -50 Z'); 84 | }); 85 | 86 | 87 | }); --------------------------------------------------------------------------------