Convert SVG paths to relative commands

Given the SVG Path element, how can I convert all path commands to relative coordinates? For example, convert this path (which includes each command, absolute and relative, alternating):

<path d="M3,7 L13,7 m-10,10 l10,0 V27 H23 v10 h10 C33,43 38,47 43,47 c0,5 5,10 10,10 S63,67 63,67 s-10,10 10,10 Q50,50 73,57 q20,-5 0,-10 T70,40 t0,-15 A5,5 45 1 0 40,20 a5,5 20 0 1 -10,-10 Z" /> 

in this equivalent way:

 <path d="m3,7 l10,0 m-10 10 l10,0 v10 h10 v10 h10 c0,6 5,10 10,10 c0,5 5,10 10,10 s10,10 10,10 s-10,10 10,10 q-23,-27 0,-20 q20,-5 0,-10 t-3,-7 t0-15 a5,5 45 1 0 -30,-5 a5,5 20 0 1 -10,-10 z"/> 

This question was motivated by this question .

+6
source share
2 answers

Snap.SVG has Snap.path.toRelative() .

 var rel = Snap.path.toRelative(abspathstring); 

Fiddle

+6
source

I changed Phrogz ' convertToAbsolute to this convertToRelative function:

 function convertToRelative(path) { function set(type) { var args = [].slice.call(arguments, 1) , rcmd = 'createSVGPathSeg'+ type +'Rel' , rseg = path[rcmd].apply(path, args); segs.replaceItem(rseg, i); } var dx, dy, x0, y0, x1, y1, x2, y2, segs = path.pathSegList; for (var x = 0, y = 0, i = 0, len = segs.numberOfItems; i < len; i++) { var seg = segs.getItem(i) , c = seg.pathSegTypeAsLetter; if (/[MLHVCSQTAZz]/.test(c)) { if ('x1' in seg) x1 = seg.x1 - x; if ('x2' in seg) x2 = seg.x2 - x; if ('y1' in seg) y1 = seg.y1 - y; if ('y2' in seg) y2 = seg.y2 - y; if ('x' in seg) dx = -x + (x = seg.x); if ('y' in seg) dy = -y + (y = seg.y); switch (c) { case 'M': set('Moveto',dx,dy); break; case 'L': set('Lineto',dx,dy); break; case 'H': set('LinetoHorizontal',dx); break; case 'V': set('LinetoVertical',dy); break; case 'C': set('CurvetoCubic',dx,dy,x1,y1,x2,y2); break; case 'S': set('CurvetoCubicSmooth',dx,dy,x2,y2); break; case 'Q': set('CurvetoQuadratic',dx,dy,x1,y1); break; case 'T': set('CurvetoQuadraticSmooth',dx,dy); break; case 'A': set('Arc',dx,dy,seg.r1,seg.r2,seg.angle, seg.largeArcFlag,seg.sweepFlag); break; case 'Z': case 'z': x = x0; y = y0; break; } } else { if ('x' in seg) x += seg.x; if ('y' in seg) y += seg.y; } // store the start of a subpath if (c == 'M' || c == 'm') { x0 = x; y0 = y; } } path.setAttribute('d', path.getAttribute('d').replace(/Z/g, 'z')); } 

Used like this: path from the question:

 var path = document.querySelector('path'); convertToRelative(path); console.log(path.getAttribute('d')); // m 3 7 l 10 0 m -10 10 l 10 0 v 10 h 10 v 10 h 10 c 0 6 5 10 10 10 c 0 5 5 10 10 10 s 10 10 10 10 s -10 10 10 10 q -23 -27 0 -20 q 20 -5 0 -10 t -3 -7 t 0 -15 a 5 5 45 1 0 -30 -5 a 5 5 20 0 1 -10 -10 z 

I also made a little phantomjs svg2rel shell utility that converts all paths to svg in this way (there is corresponding svg2abs in the same value, for good measure).

+7
source

All Articles