Sunday, May 18, 2014

Drawing Simple SVG (and XML) in Inkscape


Tonight I continue my efforts to figure out Inkscape and how best to use it to generate SVG for use in Polymer custom elements.

Last night, I was able to save an SVG file from Inkscape and load it as an <image> (not an <img> element) inside another SVG animation. Even so, I am still not quite satisfied with how I use Inkscape. I ignored it last night, but the SVG that is produced starts 1000 pixels away from the origin and is then translated back to the center:
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="10"
   height="10">
  <g transform="translate(0,-1042.3622)">
    <path
       d="m 239.99999,318.07648 a 34.285713,37.142857 0 1 1 -68.57142,0 34.285713,37.142857 0 1 1 68.57142,0 z"
       transform="matrix(0.14380379,0,0,0.13275542,-24.582993,1005.1358)"
       style="fill:#d40000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
  </g>
</svg>
For a small, icon-sized SVG that seems silly. Also in there is a circle with 30+ pixel radius that us then transformed to fit inside a 10x10 pixel frame of reference. Again, this bothers me—partially because additional math gets harder because of these matrixes and transforms, partly because the 1 pixel wide stroke around the object is barely visible when shrunk, but mostly because it seems so completely unnecessary.

Simplify


One way to simplify the resulting SVG is to use Inkscape's “Simplify” feature for paths. After I scale and move my object to the correct location on my 10x10 document:



I choose Path → Simplify, then save the SVG, which results in:
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="10"
   height="10">
  <g transform="translate(0,-1042.3622)">
    <path
       d="m 9.7494748,1047.3354 c 0.027392,1.8967 -1.2204621,3.7206 -2.9909977,4.3951 -1.7387873,0.7079 -3.8728512,0.2425 -5.150298,-1.1367 -1.33070755,-1.3565 -1.68575613,-3.5433 -0.86294089,-5.2541 0.76651319,-1.6943 2.60602119,-2.8204 4.46410649,-2.7235 1.9127635,0.046 3.7001042,1.3877 4.2919905,3.2045 0.1650043,0.4868 0.2484206,1.0008 0.2481396,1.5147 z"
       style="opacity:0.89000029;fill:#d40000;fill-opacity:1;stroke:#000000;stroke-width:0.59033614;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
  </g>
</svg>
That does not appear to be a huge win. On the one hand, I no longer have that confusing transform attribute. On the other hand, the draw attribute is much, much bigger. Also, I still have that pesky translate on the <g> group tag.

One option here is to use the XML Editor in Inkscape to move the <path> out of the <g> tag so that that the path is a direct child of the <svg> tag itself. If I do that, and then “Simplify,” I get a path without transform (though still a confusing path).

It is not until I get a comment on last night's post from Emanuele Sabetta that I fully realize what I am doing by moving the path out of the group. In fact, I am moving my current object out of Inkscape's current layer and manually placing it in the root layer. Furthermore, Emanuele suggests doing just that—drawing in the root layer—as the best approach for simple SVG icons.

Armed with this knowledge, I start anew.

Drawing in the Root Layer


I choose File → New → icon_16x16 as the closest to what I want. I show the grid (shortcut is #), the Fill and Stroke controls (shortcut is Ctrl Shift F), and the Layer controls (shortcut is Ctrl Shift L). The result is something like:



The first thing I do, per Emanuele's advice, is delete the current layer from the Layer controls:



Now, my drawing goes right in the root layer, which should simplify things from the outset.

Next, I select the create circle tool:



The reason that I began with the grid showing was so that I knew where to first start drawing my circle. Since I am going to have a stroke (outline) around the circle, I do not want the drawing to start exactly on the corner of my 16x16 drawing area—the stroke would wind up outside. Instead, I begin by clicking one grid down and one over:



I then drag to the opposite side, holding the Ctrl key to constrain the drawing to a circle:



When I save that as plain SVG (not Inkscape SVG), I get the much, much simpler:
<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="16"
   height="16">
  <path
     d="M 15,8 A 7,7 0 1 1 1,8 7,7 0 1 1 15,8 z"
     style="fill:#d40000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</svg>
That is exactly what I have been trying to get all along, so yay!

Huge thanks (again) to Emanuele for the pointers. Between those and learning from my own dumb mistakes, I may finally be getting the hang of this Inkscape thing. I am unsure if there is a way to draw a circle, then resize it so that the resulting drawing path is this simple. That is probably not a common use case as people will more often than not want more complex shapes that require complex paths anyway. For those, the “Simplify” option will likely come in handy. I will pick back up with that tomorrow for some other toppings for my <x-pizza> custom Polymer element. I also need to rethink where my SVG assets go as things are changing in Dart Pub. But that's for tomorrow.

For tonight, yay!


Day #67

No comments:

Post a Comment