A powerful, dependency-free JavaScript library for extracting points along SVG paths with configurable density and vertex preservation. Perfect for converting SVG graphics into arrays of coordinate points for use in animations, data visualization, or drawing applications.
- 🎯 Extract points from any SVG element: paths, lines, circles, rectangles, ellipses, polygons, and polylines
- ⚙️ Configurable point density: Control the spacing between extracted points
- 🔒 Vertex preservation: Guarantees that all corners and vertices are included in results
- 📊 Element metadata: Extract points with information about source elements
- 🧮 Utility methods: Built-in bounding box, length, and center calculations
- 📏 Coordinate normalization: Scale results to specific dimensions
- 🌐 Universal compatibility: Works in both Node.js and browser environments
- 🔧 Zero dependencies: No external libraries required for core functionality
- 📝 TypeScript support: Full type definitions included
- 🛡️ Robust error handling: Graceful handling of malformed SVG content
- 🎨 Transform support: Basic support for SVG transforms
Currently available as a standalone file. Download svg-to-points.js from this repository.
Future releases will be available on:
- NPM:
npm install svg-to-points(coming soon) - CDN:
<script src="https://cdn.example.com/svg-to-points.js"></script>(coming soon)
<script src="svg-to-points.js"></script>
<script>
const extractor = new SVGPathExtractor({ pointDensity: 8 });
const svgContent = `
<svg width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="30" />
</svg>
`;
extractor.extractPoints(svgContent).then(paths => {
console.log('Extracted paths:', paths);
// paths[0] = [{ x: 80, y: 50 }, { x: 79.3, y: 53.9 }, ...]
});
</script>const SVGPathExtractor = require('./svg-to-points.js');
const extractor = new SVGPathExtractor({
pointDensity: 5, // 5 units between points
densityFactor: 0.0075, // Auto-density factor
closePaths: false // Don't close paths by default
});
// From string
const svgContent = `...your SVG content...`;
const paths = await extractor.extractPoints(svgContent);
// From file (Node.js only)
const paths = await extractor.extractPointsFromFile('./path/to/file.svg');
console.log(`Extracted ${paths.length} paths with ${paths[0]?.length} points each`);import SVGPathExtractor from './svg-to-points.js';
const extractor = new SVGPathExtractor();
const paths = await extractor.extractPoints(svgContent);new SVGPathExtractor(options?)| Option | Type | Default | Description |
|---|---|---|---|
pointDensity |
number | null |
null |
Fixed distance between points. If null, automatically calculated |
densityFactor |
number |
0.0075 |
Factor for automatic density calculation |
maxPoints |
number |
1000000 |
Maximum points per path (safety limit) |
includeOnly |
string[] | null |
null |
Only process specific element types |
excludeElements |
string[] |
[] |
Exclude specific element types |
normalizeToSize |
{width: number, height: number} | null |
null |
Normalize all paths to specific dimensions |
closePaths |
boolean |
true |
Close closed shapes by duplicating first point at end |
Extracts points from SVG content string.
- Parameters:
svgContent(string): SVG markup as stringpointDensity(number, optional): Override density for this extraction
- Returns:
Promise<Array<Array<{x: number, y: number}>>>
Extracts points with metadata about source elements.
- Parameters:
svgContent(string): SVG markup as stringpointDensity(number, optional): Override density for this extraction
- Returns:
Promise<Array<{points: Point[], element: string, id?: string, className?: string, attributes: object}>>
Node.js only - Extracts points from SVG file.
- Parameters:
filePath(string): Path to SVG filepointDensity(number, optional): Override density for this extraction
- Returns:
Promise<Array<Array<{x: number, y: number}>>>
Calculate bounding box of all paths.
- Parameters:
paths(Array<Array<{x: number, y: number}>>) - Returns:
{x: number, y: number, width: number, height: number}
Calculate total length of all paths.
- Parameters:
paths(Array<Array<{x: number, y: number}>>) - Returns:
number
Calculate center point (centroid) of all paths.
- Parameters:
paths(Array<Array<{x: number, y: number}>>) - Returns:
{x: number, y: number}
| Element | Support | Vertex Preservation | Notes |
|---|---|---|---|
<path> |
✅ Full | ✅ Yes | Custom parser with Bézier curve support |
<line> |
✅ Full | ✅ Yes | Linear interpolation with endpoints |
<circle> |
✅ Full | N/A | Parametric circle generation |
<rect> |
✅ Full | ✅ Yes | Perimeter tracing with exact corners |
<ellipse> |
✅ Full | N/A | Parametric ellipse generation |
<polygon> |
✅ Full | ✅ Yes | All vertices guaranteed in output |
<polyline> |
✅ Full | ✅ Yes | All vertices guaranteed in output |
<image> |
⏭️ Ignored | N/A | Raster images are skipped |
<text> |
⏭️ Ignored | N/A | Text elements are skipped |
const extractor = new SVGPathExtractor({ pointDensity: 8 });
const svg = `
<svg viewBox="0 0 200 200">
<circle cx="100" cy="100" r="50" />
<rect x="25" y="25" width="150" height="150" />
</svg>
`;
const paths = await extractor.extractPoints(svg);
console.log(`Circle: ${paths[0].length} points`);
console.log(`Rectangle: ${paths[1].length} points`);const pathsWithMetadata = await extractor.extractPointsWithMetadata(svg);
pathsWithMetadata.forEach(pathData => {
console.log(`Element: ${pathData.element}`);
console.log(`ID: ${pathData.id || 'none'}`);
console.log(`Points: ${pathData.points.length}`);
console.log(`Attributes:`, pathData.attributes);
});const paths = await extractor.extractPoints(svg);
// Get bounding box
const bbox = extractor.getBoundingBox(paths);
console.log(`Size: ${bbox.width} x ${bbox.height}`);
// Get total length
const totalLength = extractor.getTotalLength(paths);
console.log(`Total length: ${totalLength.toFixed(2)} units`);
// Get center point
const center = extractor.getCenter(paths);
console.log(`Center: (${center.x}, ${center.y})`);const extractor = new SVGPathExtractor({
pointDensity: 5,
includeOnly: ['rect', 'circle'], // Only process rectangles and circles
normalizeToSize: { width: 100, height: 100 }, // Scale to 100x100
closePaths: true // Close closed shapes
});
const paths = await extractor.extractPoints(svg);// Only process specific elements
const extractor = new SVGPathExtractor({
includeOnly: ['path', 'polygon']
});
// Or exclude specific elements
const extractor2 = new SVGPathExtractor({
excludeElements: ['text', 'image']
});const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const paths = await extractor.extractPoints(svgContent);
paths.forEach(path => {
ctx.beginPath();
path.forEach((point, index) => {
if (index === 0) {
ctx.moveTo(point.x, point.y);
} else {
ctx.lineTo(point.x, point.y);
}
});
ctx.stroke();
});Point density determines the spacing between extracted points:
- Low density (20-50): Fewer points, good for simple shapes or performance
- Medium density (5-15): Balanced detail and performance
- High density (1-3): Maximum detail, good for complex curves
- Auto density: Automatically calculated based on SVG size
// Different density examples
const lowDetail = await extractor.extractPoints(svg, 20); // ~10 points
const mediumDetail = await extractor.extractPoints(svg, 8); // ~25 points
const highDetail = await extractor.extractPoints(svg, 2); // ~100 points
const autoDetail = await extractor.extractPoints(svg); // Auto-calculatedThe library guarantees that all critical vertices (corners, intersections) are included in the output:
- Rectangle corners: All 4 corners are exactly preserved
- Polygon vertices: All original vertices included regardless of density
- Path endpoints: Start and end points of path segments
- Line endpoints: Both ends of line elements
// Even with low density, vertices are preserved
const paths = await extractor.extractPoints(`
<polygon points="0,0 100,0 50,50" />
`, 50); // Very low density
// All 3 vertices (0,0), (100,0), (50,50) will be in the resultFor Node.js usage, optionally install XML parser dependency for better performance:
npm install xmldomThe library will automatically detect and use it. If not available, it falls back to basic parsing.
The library includes comprehensive test files:
tests/test-suite.js: Automated test suite (14 tests)index.html: Interactive demo and visual testingtests/: Test SVG files for various scenarios
Run tests using npm or Node.js directly:
npm test
# or
node tests/test-suite.jsCurrent Version: 1.0.0 (Beta)
Status: Ready for production use, pending publication
- NPM package publication
- CDN distribution
- Additional transform support
- Arc path support improvements
- Performance optimizations
This is currently a standalone project. Contributions and feedback are welcome!
For bug reports or feature requests, please create an issue or contact the maintainer.
MIT License - see the LICENSE file for details.
- Vertex Preservation: All corners and vertices are guaranteed in output
- Element Metadata: Extract points with source element information
- Utility Methods: Built-in bounding box, length, and center calculations
- Coordinate Normalization: Scale results to specific dimensions
- Path Closing: Option to close closed shapes
- Enhanced Path Parser: Support for cubic and quadratic Bézier curves
- Element Filtering: Include/exclude specific element types
- Complex path arcs may have reduced precision in Node.js fallback mode
- Transform support is basic (matrix and simple transforms only)
- Very large SVGs may hit the
maxPointssafety limit (configurable) - Some edge cases in complex nested transforms
svg-to-points.js: Main library fileindex.d.ts: TypeScript definitionsindex.html: Interactive demo page (GitHub Pages)examples/: Usage examples (browser and Node.js)tests/: Test suite and test SVG filespackage.json: NPM package configurationLICENSE: MIT license file
Ready for production use • Vertex-preserving algorithm • Zero dependencies • Universal compatibility