maker.js
maker.js copied to clipboard
SVG Import - some paths fail to import
Hi,
I noticed makerJs sometimes failed to import some SVG paths generated by other libraries.
M 0 0 L 10 0 will import ok.
M 0 0 10 0 will fail to import.
The SVG Move Path command spec mentions:
Move the begining of the next subpath to the coordinate x,y. All subsequente pair of coordinates are considered implicite absolute LineTo (L) command.
I suspect the SVG Importer is not handling this part of the spec.
Simple demo below (can copy and paste into https://maker.js.org/playground):
var makerjs = require('makerjs');
// Draw a square from origin 0,0 with sides of 10 units.
// Equivalent to:
// <svg xmlns="http://www.w3.org/2000/svg">
// <path stroke="red" fill="none" d="M 0 0 L 10 0"/>
// <path stroke="red" fill="none" d="M 10,0 L 10,10"/>
// <path stroke="red" fill="none" d="M 10 10 0 10"/>
// <path stroke="red" fill="none" d="M 0,10 0,0"/>
// </svg>
var svgTestPaths =
{
path1: "M 0 0 L 10 0", // Top (ok)
path2: "M 10,0 L 10,10", // Right (ok)
path3: "M 10 10 0 10", // Bottom (failed)
path4: "M 0,10 0,0" // Left (failed)
};
this.models =
{
path1: makerjs.importer.fromSVGPathData(svgTestPaths.path1),
path2: makerjs.importer.fromSVGPathData(svgTestPaths.path2),
path3: makerjs.importer.fromSVGPathData(svgTestPaths.path3),
path4: makerjs.importer.fromSVGPathData(svgTestPaths.path4)
};
this.notes =
[
'# SVG path import test',
'Draw four sides of a square using various SVG Path syntax. ' +
'Note the bottom and left paths fail to import'
].join('\n');
Wow, good catch. I'm sure that I haven't implemented that part of the spec.
Until I do, do you have a good workaround?
Yep, I've been able to workaround it using https://github.com/jkroso/parse-svg-path
const parseSvgPath = require('parse-svg-path');
function fixPath(path)
{
var resolvedParts = [];
parseSvgPath(path).forEach(function(command)
{
resolvedParts.push(command.join(' '));
});
return resolvedParts.join(' ');
}
Good to see you have a workaround, as I might not get to the fix until after some other fixes. Thanks for posting! 🥇
No worries, great work on this lib by the way. makerjs.path.expand solved a huge roadblock for me.
Oh, happy day! Thank you @ldstein, this was driving me nuts. Here's my test case:
const makerjs = require('makerjs');
/* original SVG:
<svg width="60" height="60">
<path d="M0 30a30 30 0 0 1 60 0 30 30 0 0 1-60 0zm10 0a20 20 0 0 1 40 0 20 20 0 0 1-40 0z" vector-effect="non-scaling-stroke" stroke-linecap="round" fill-rule="evenodd" font-size="12" stroke="#000" stroke-width=".25mm" fill="none"/>
</svg>
*/
const path = "M0 30a30 30 0 0 1 60 0 30 30 0 0 1-60 0zm10 0a20 20 0 0 1 40 0 20 20 0 0 1-40 0z";
let model = makerjs.importer.fromSVGPathData(path);
let svg = makerjs.exporter.toSVG(model);
console.log(svg);
/* output:
<svg width="60" height="30" viewBox="0 0 60 30"><g id="svgGroup" stroke-linecap="round" fill-rule="evenodd" font-size="9pt" stroke="#000" stroke-width="0.25mm" fill="none" style="stroke:#000;stroke-width:0.25mm;fill:none"><path d="M 60 30 A 30 30 0 0 0 0 30 L 60 30 Z M 50 30 A 20 20 0 0 0 10 30 L 50 30 Z" vector-effect="non-scaling-stroke"/></g></svg>
*/
const parseSvgPath = require('parse-svg-path');
function fixPath(path)
{
var resolvedParts = [];
parseSvgPath(path).forEach(function(command)
{
resolvedParts.push(command.join(' '));
});
return resolvedParts.join(' ');
}
const path2 = fixPath(path);
model = makerjs.importer.fromSVGPathData(path2);
svg = makerjs.exporter.toSVG(model);
console.log(svg);
/* output:
<svg width="60" height="60" viewBox="0 0 60 60"><g id="svgGroup" stroke-linecap="round" fill-rule="evenodd" font-size="9pt" stroke="#000" stroke-width="0.25mm" fill="none" style="stroke:#000;stroke-width:0.25mm;fill:none"><path d="M 60 30 A 30 30 0 0 0 0 30 A 30 30 0 0 0 60 30 Z M 50 30 A 20 20 0 0 0 10 30 A 20 20 0 0 0 50 30 Z" vector-effect="non-scaling-stroke"/></g></svg>
*/



If you need more examples... https://github.com/jscad/sample-files
Thanks for posting your solution @mrbluecoat 👍
I managed to get this working, I'd be happy to submit a pull request
@ggoodkey thank you, a PR would be welcome!
Seems like the PR was merged but there has not been a recent makerjs release containing it.
@rla thanks for the reminder, 0.17.2 now published.