I'm working on a project where I need to parse svg path data.
Right now we're loading an svg, looking for the path tag, and pulling out it's d attribute.
For some of the artwork we'll get path data that is made up of coordinates which we can translate into the data types we need. E.g.
But other times the d value is in a more g-code-esq format.
Like in this case I drew a rectangle, converted it to a compound path:
And when I export it and look at the svg I get a d value like this:
Which we can't easily parse for the project.
My questions are:
How do I read this second format? It doesn't seem to fit what I'm reading on MDN so I suspect there's some other documentation I need to refer to: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
For illustrator users, is there a way of changing the format when exporting?
I know that this seems like more of an art question than a programming question, but I'm trying to understand the underlying reasoning behind the svg data structure so I can better parse it.
Oh! Oh ok, I was 100% misunderstanding the path data that I was reading. I didn't realize that the delimiting information was based on the letter. My brain wanted some specific character as a delimiter like a comma or pipe.
So reading (and in some cases re-reading :| ) the documentation, when I see:
M753,315H435.27V165H753Z
I can read that as:
M753,315 Move to x,y coordinates x: 753 y:315
H435.27 Starting at the current location, draw a horizontal line to the absolute x coordinate of 435.27
V165 Starting at the current location, draw a vertical line to the absolute y coordinate of 165
H753 Starting at the current location, draw a horizontal line to the absolute x coordinate of 753
ZDraw a straight line to the initial point of this path to close the path. This doesn't necessarily mean a horizontal or vertical line, but the coincidence that we're at the same x coordinate that we started at means that if we draw a straight line we will get a vertical line to complete the rectangle
That seems right. Anything I missed or misunderstood?
Also, thank for all of the links. I appreciate the points :clap: :bows:
Suppose I have a svg path and a piece of text. I want to figure out where they intersect. I'm not really sure where to start, because the svg path's getBBox() function does not help.
Where should I start?
You have the text bounding box via getBBox(). Unfortunately, as you may have already discovered, that is not a tight bounding box of the glyphs. It includes the full descender and ascender heights of the font. However it should get you a reasonable approximation.
The next step is to determine where the path hits the bounding box. Getting a perfect mathematical solution is very hard, but there are iterative approaches that are much easier and give good results.
Path elements have a couple of DOM functions that can help: getTotalLength() and getPointAtLength(). You can step along the path from 0 to the path length, calling getPointAtLength(), until the point returned is inside the text bbox.
If you want to get more accurate and determine which character in the text touches the line, there are some DOM functions on SVG text elements that should be useful. For instance, `getExtentOfChar(n) returns the bounds of the nth character in the text.
Looking for a tool to convert something like
M10 20L0 0 5 5 10 10
from the absolute position to relative, something like:
M10 20l-10 -20 5 5 5 5
Notice the uppercase L for absolute and lowercase l for relative?
Open Inkscape and select File, Inkscape Preferences (or Shift + Ctrl + P)
Select SVG output
In the path data section untick Allow relative coordinates or select always use absolute coordinates depending on your version of Inkscape.
This will only affect newly created paths or existing objects for which a rewrite of the path data is triggered. For existing paths:
Select Edit, then Select All in All Layers.
Use the arrow key to nudge the selection (e.g. one step up and one back down again). This will trigger a rewrite of the path data in d which will follow the changed preferences for absolute path values.
This works for Inkscape 0.48
For who's still searching for this tool. There is one made by Lea Verou on codepen that convert paths to relative or absolute.
Example convert this:
M233.51,56.8c-0.57,0.24-1.33,0.52-2.28,0.86c-0.95,0.33-1.93,0.5-2.92,0.5s-1.84-0.27-2.53-0.82
c-0.69-0.55-1.03-1.49-1.03-2.82V36.25h7.85V28.9h-7.85V16.77h-9.56V28.9h-17.84V16.77h-9.56V28.9h-4.92v7.35h4.92v21.48
c0,1.67,0.26,3.08,0.79,4.25c0.52,1.17,1.22,2.12,2.1,2.85c0.88,0.74,1.9,1.27,3.07,1.61c1.16,0.33,2.41,0.5,3.75,0.5
c2.05,0,4-0.28,5.85-0.86c1.86-0.57,3.42-1.14,4.71-1.71l-1.93-7.56c-0.57,0.24-1.33,0.52-2.28,0.86c-0.95,0.33-1.93,0.5-2.92,0.5
c-1,0-1.84-0.27-2.53-0.82c-0.69-0.55-1.03-1.49-1.03-2.82V36.25h17.84v21.48c0,1.67,0.26,3.08,0.79,4.25
c0.52,1.17,1.22,2.12,2.1,2.85c0.88,0.74,1.9,1.27,3.07,1.61c1.16,0.33,2.41,0.5,3.75,0.5c2.05,0,4-0.28,5.85-0.86
c1.86-0.57,3.42-1.14,4.71-1.71L233.51,56.
Into this:
M233.51,56.8c-0.57,0.24,-1.33,0.52,-2.28,0.86c-0.95,0.33,-1.93,0.5,-2.92,0.5s-1.84,-0.27,-2.53,-0.82c-0.69,-0.55,-1.03,-1.49,-1.03,-2.82v-18.27h7.85v-7.35h-7.85v-12.13h-9.56v12.13h-17.84v-12.13h-9.56v12.13h-4.92v7.35h4.92v21.48c0,1.67,0.26,3.08,0.79,4.25c0.52,1.17,1.22,2.12,2.1,2.85c0.88,0.74,1.9,1.27,3.07,1.61c1.16,0.33,2.41,0.5,3.75,0.5c2.05,0,4,-0.28,5.85,-0.86c1.86,-0.57,3.42,-1.14,4.71,-1.71l-1.93,-7.56c-0.57,0.24,-1.33,0.52,-2.28,0.86c-0.95,0.33,-1.93,0.5,-2.92,0.5c-1,0,-1.84,-0.27,-2.53,-0.82c-0.69,-0.55,-1.03,-1.49,-1.03,-2.82v-18.28h17.84v21.48c0,1.67,0.26,3.08,0.79,4.25c0.52,1.17,1.22,2.12,2.1,2.85c0.88,0.74,1.9,1.27,3.07,1.61c1.16,0.33,2.41,0.5,3.75,0.5c2.05,0,4,-0.28,5.85,-0.86c1.86,-0.57,3.42,-1.14,4.71,-1.71l-1.97,-7.57z
https://codepen.io/leaverou/pen/RmwzKv
In settings, under "SVG Output", set "Path string format" to "Absolute" and save as plain SVG. You may have to nudge the object so Inkskape will reset the 'd' attribute for the path.
Found a tool called Inkscape which allows saving to relative.
To do this:
New document, create a random pencil path, and save the SVG. Close inkscape.
Edit saved file in a text editor. Find and replace the pencil path with your path
Re-open the document in Inkscape. Locate and move your path. Save.
Edit the file again and look for the new relative path.
TADA
I am trying to copy paths from inkscape into Raphael (individual countries), the problem is the moveTo is way off, how do I make it display on the relatively correct position on the canvas?
If you're trying to draw a path on a canvas in a relative position, you need to transform all of the absolute coordinates to relative coordinates. I had the same problem recently and resorted to a calculator and paper (it was a short path, and wasn't worth it to attack programatically). There are a few tools out there that claim to be able to do these transformations, but in my experience they were either incomplete or outdated links.
The problem is that Inkscape has already decided for you that you want your SVG files optimized for size, and will switch back and forth from relative to absolute whenever it would save a few bytes. Essentially, what you would need to do is iterate through the path, keeping track of your position, compare each absolute node to the previous node (or the origin, if it's the initial moveTo), and replace any absolute coordinates with the difference.
The Inkscape preferences have an option to force absolute coordinates, (uncheck Preferences->SVG Output->Allow relative coordinates) which may make the transformation a little easier.