Home > Net >  Set transform and size of <use> to allow it to be saved as .svg files correctly for editing
Set transform and size of <use> to allow it to be saved as .svg files correctly for editing

Time:10-14

I created an <svg> element with JavaScript, here are my codes:

<svg xmlns:xlink="http://www.w3.org/1999/xlink">
    <svg id="stroke_carrot" fill="#000000" viewBox="0 0 50 50" width="0px" height="0px">
 
        <path d="M30 13c-1-3-5-4-7-2h-1l1-11h-3l-1 
                                    9-4-7-3 1 5 8-8-4-1 2 9 5h-1c-2 
                                    2-3 5-2 7l2 2 5-3 1 2-5 3 8 9 5-3 
                                    2 2-5 3 12 14 3-2-8-25-5 3-1-2 5-3-3-8">
        </path>
                                  
    </svg>

  <defs>
    <pattern id="myPat" patternUnits="userSpaceOnUse" width="88" height="88" patternTransform="translate(0,0) rotate(0)">
        <use width="44" height="44" xlink:href="#stroke_carrot"  style="transform: translate3d(40px, 0px, 0px) rotate(80deg);"></use>
        <use width="44" height="44" xlink:href="#stroke_carrot" style="transform: translate3d(60px, 0px, 0px) rotate(50deg);"></use>
    </pattern>
  </defs>
  
  <rect x="0px" y="0px" width="300px" height="200px" fill="url(#myPat)"> </rect>

</svg>

The <svg> looks like this on the webpage, you can run the codes to see it.

SVG on the webpate

Then I save this <svg> element as .svg file, and open it in Adobe Illustrator to edit it. It becomes different, like this:

SVG in Adobe Illustrator

Apparently, the transform attributes (position and rotation) do not work. Do you know how to make the transform work? I want to save the <svg> element to a same looking .svg file that I can edit in Adobe Illustrator.

I tried to use x= and y= to set the position in the codes, then it works in the Illustrator. For the rotation I don't find a way to do. Also, since the other features of my site are not compatible with x and y (see this question), so I still hope I could be able to use transform to achieve it.

CodePudding user response:

It does not work to set transform attribute/style for the <use> element directly, but we can embedded the <use> in the <svg> and <g>. In this way we can also resize and recolor the referenced element (the <path> in this case).

Now it can be displayed properly in the browser, as well as be saved as an .svg file and opened for editing in Adobe Illustrator

<svg xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink">
 
    <svg fill="#000000" viewBox="0 0 50 50" width="0px" height="0px">
        <path  id="stroke_carrot" d="M30 13c-1-3-5-4-7-2h-1l1-11h-3l-1 
                                    9-4-7-3 1 5 8-8-4-1 2 9 5h-1c-2 
                                    2-3 5-2 7l2 2 5-3 1 2-5 3 8 9 5-3 
                                    2 2-5 3 12 14 3-2-8-25-5 3-1-2 5-3-3-8">
        </path>
    </svg>

    <defs>
        <pattern id="myPat" patternUnits="userSpaceOnUse" width="88" height="88"  patternTransform="translate(0,0) rotate(0)">
            <g transform = "rotate(80 45 25) translate(20 0)">
                <svg width="50" height="50" viewBox="0 0 50 50"  fill="orange">
                    <use xlink:href="#stroke_carrot"></use>
                </svg>
            </g>
            
            <g transform = "rotate(50 65 25) translate(40 0)">
                <svg width="50" height="50" viewBox="0 0 50 50"  fill="blue">
                    <use xlink:href="#stroke_carrot"></use>
                </svg>
            </g>
        </pattern>
    </defs>
  
    <rect x="0px" y="0px" width="300px" height="200px" fill="url(#myPat)"> </rect>
</svg>

Note:

  1. We need to wrap the <svg> in <g>, and set transform for <g>, to make it work for Chrome. More details see: Transform is not applied on Embedded SVGs Chrome
  2. Rotate: The rotate(<a> [<x> <y>]) transform function specifies a rotation by a degrees about a given point.
  3. Since I want the carrot rotates around its own center, I set the parameters for the transform attribute like this:transform = "rotate(degree width/2 x height/2 y) translate(x y)"

CodePudding user response:

You can apply transform attributes directly to <use> elements.

Besides, nested svgs usually cause a lot of troubles for vector graphic applications – so be careful!

Example – tested in AI cs6 (so quite old..) and inkscape

<svg width="300px" height="200px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
        <path id="stroke_carrot" 
        d="M30 13c-1-3-5-4-7-2h-1l1-11h-3l-1 
        9-4-7-3 1 5 8-8-4-1 2 9 5h-1c-2 
        2-3 5-2 7l2 2 5-3 1 2-5 3 8 9 5-3 
        2 2-5 3 12 14 3-2-8-25-5 3-1-2 5-3-3-8">
        </path>
    <pattern id="myPat" patternUnits="userSpaceOnUse" width="88" height="88" >
        <use fill="orange" href="#stroke_carrot" xlink:href="#stroke_carrot" transform="rotate(80 45 25) translate(20 0)" />
        <use fill="blue" href="#stroke_carrot" xlink:href="#stroke_carrot" transform="rotate(50 65 25) translate(40 0)" />
    </pattern>
  </defs>
  <rect x="0px" y="0px" width="300px" height="200px" fill="url(#myPat)"> </rect>
</svg>

Some common practices for standalone or editable svgs

  • include namespace attributes like xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" for best compatibility – well done!
  • include legacy href syntax xlink:href for <use> references. Although these are classified as deprecated – they are still needed by a lot of apps. You can also add the recommended href.– also well done!
  • use more "conservative" styling/formatting methods and features:
    A lot of applications only support a reduced set of svg features (or vaguely described as svg 1.0-1.1 compatibility – not by any means precise)
  • transformations: As recommended by @Robert Longson: svg transform attributes tend to be more reliable:
    3d transformations like translate3d might not be interpreted correctly.
    Related properties like transform-origin or transform-box for specifying e.g. a pivot point for a rotation might also be ignored by some apps. A workaround can be to convert all transformations to a matrix.
  • avoid nested svgs – a lot of applications will struggle to calculate these nested viewBoxes or x/y offsets.
    In your case you can easily define your carrot path within the <defs> (or create a <symbol>).
  • Related