How to use animateTransform cx cy values properly?

144 Views Asked by At

I am trying to make an animated loading icon in svg, although whenever I check the result in Chrome, or Edge, the rotation animation doesn't react on the cx/cy values (only if I set them to zero, it will be properly rotated, otherwise there is a bit of swing).

I am using it in Qt with QSvgWidget and there the example below works fine. I just want to understand why it doesn't work on Chrome.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="23mm"
   height="23mm"
   viewBox="0 0 23 23"
   version="1.1"
   id="svg8"
   inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
   sodipodi:docname="loading_static.svg">
  <defs
 id="defs2">
<linearGradient
   inkscape:collect="always"
   id="linearGradient2832">
  <stop
     style="stop-color:#e9e9e9;stop-opacity:1"
     offset="0"
     id="stop2841" />
  <stop
     style="stop-color:#ffffff;stop-opacity:0"
     offset="1"
     id="stop2843" />
</linearGradient>
<linearGradient
   id="linearGradient2781"
   osb:paint="solid">
  <stop
     style="stop-color:#e5e5e5;stop-opacity:1;"
     offset="0"
     id="stop2779" />
</linearGradient>
<linearGradient
   inkscape:collect="always"
   xlink:href="#linearGradient2832"
   id="linearGradient2846"
   gradientUnits="userSpaceOnUse"
   x1="86.672661"
   y1="84.384331"
   x2="90.090706"
   y2="84.979637" />
  </defs>
  <sodipodi:namedview
 id="base"
 pagecolor="#ffffff"
 bordercolor="#666666"
 borderopacity="1.0"
 inkscape:pageopacity="0.0"
 inkscape:pageshadow="2"
 inkscape:zoom="4"
 inkscape:cx="49.995012"
 inkscape:cy="42.458459"
 inkscape:document-units="mm"
 inkscape:current-layer="layer1"
 inkscape:document-rotation="0"
 showgrid="false"
 fit-margin-top="0"
 fit-margin-left="0"
 fit-margin-right="0"
 fit-margin-bottom="0"
 inkscape:window-width="1267"
 inkscape:window-height="1040"
 inkscape:window-x="104"
 inkscape:window-y="0"
 inkscape:window-maximized="0" />
  <metadata
 id="metadata5">
<rdf:RDF>
  <cc:Work
     rdf:about="">
    <dc:format>image/svg+xml</dc:format>
    <dc:type
       rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
    <dc:title></dc:title>
  </cc:Work>
</rdf:RDF>
  </metadata>
  <g
 inkscape:label="Layer 1"
 inkscape:groupmode="layer"
 id="layer1"
 transform="translate(-69.67318,-75.994617)">
<path
   style="fill:none;stroke:url(#linearGradient2846);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
   id="path833"
   sodipodi:type="arc"
   sodipodi:cx="81.170387"
   sodipodi:cy="87.492027"
   sodipodi:rx="10"
   sodipodi:ry="10"
   sodipodi:start="0"
   sodipodi:end="5.2186587"
   sodipodi:arc-type="arc"
   d="M 91.170387,87.492027 A 10,10 0 0 1 83.8004,97.139982 10,10 0 0 1 72.55378,92.566876 10,10 0 0 1 74.008018,80.513455 10,10 0 0 1 86.01957,78.746433"
   sodipodi:open="true"/>
  </g>

<animateTransform
    from="0 11.5 11.5"
    to="360 11.5 11.5"
    attributeName="transform"
    type="rotate"
    repeatCount="indefinite"
    dur="1300ms"
/>
</svg>
 

1

There are 1 best solutions below

0
On

If you want this shape to rotate without wobbling, you have to make sure it rotates about a point in its exact centre. But in your code, it's very difficult to figure out where the centre of this shape is, so no wonder you're having trouble getting it to work.

For something like this, you would probably be better off not using Inkscape. Instead, here's a simple example made from scratch:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="23mm" height="23mm" viewBox="0 0 23 23">
  <g transform="translate(11.5,11.5)">
    <path d="M9.5,0C9.5,5.243 5.243,9.5 0,9.5C-5.243,9.5 -9.5,5.243 -9.5,0C-9.5,-5.243 -5.243,-9.5 0,-9.5C2.622,-9.5" fill="none" stroke="#000" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="4">
      <animateTransform from="0" to="360" attributeName="transform" type="rotate" repeatCount="indefinite" dur="1300ms"/>
    </path>
  </g>
</svg>

The path element describes a three-quarter circle of radius 9.5 units centered on the origin. The animateTransform element inside it causes it to rotate around the origin (so no need for the additional x and y values in the rotation parameters), and the outer g element transforms the whole thing to the middle of the view box.