1

I'm working on making a simple loading spinner element with SVG. It works excellently in Chrome, but not in other browsers. In IE, the animation doesn't work at all. More troubling, in FF, the animation works but the rotation is not centered at the right location.

What can I do to make it rotate correctly in FF? (Edit: It actually works correctly in FF 42alpha.) Is there anything I can do to get it to work in IE? (Targeting the current version of these browsers)

The snippet below contains the relevant CSS and HTML:

svg.spinner {
  display: block;
  width: 50px;
}
svg.spinner path {
  fill-opacity: 0;
  stroke-width: 11;
}
svg.spinner path.track {
  stroke: rgba(92, 112, 128, 0.2);
}
svg.spinner path.head {
  stroke: rgba(92, 112, 128, 0.5);
  stroke-linecap: round;
  /* -webkit-transform-origin: 50px 50px; */
  -ms-transform-origin: 50px 50px;
  transform-origin: 50px 50px;
  -webkit-animation: spin 2s linear infinite;
  animation: spin 2s linear infinite;
}
@-webkit-keyframes spin {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  to {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes spin {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  to {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
<svg class="spinner" viewBox="0 0 100 100">
  <path class="track" d="M 50,50 m 0,-44.5 a 44.5,44.5 0 1 1 0,89 a 44.5,44.5 0 1 1 0,-89"></path>
  <path class="head" d="M 91.81632162497291 65.21989637799226 A 44.5 44.5 0 0 0 50 5.5"></path>
</svg>
JKillian
  • 18,061
  • 8
  • 41
  • 74
  • FF has/had a different interpretation of `transform-origin` than Chrome does. I believe FF used the 0.0 point of the SVG while Chrome uses the center of the SVG. That's why libraries like Snap.svg and Greensock were created. A search through the related questions on the left --> might turn something up for you. – Paulie_D Sep 11 '15 at 19:47
  • I think this one is on point in case my information is incorrect or out of date - http://stackoverflow.com/questions/24203492/transform-origin-on-svgs-in-firefox – Paulie_D Sep 11 '15 at 19:50
  • Was about to link to the same question, @Paulie_D! ;) [Looks like](https://connect.microsoft.com/IE/feedbackdetail/view/1046003/css-transforms-feature-detection-not-working-on-svg-elements) it still hasn't been patched for IE yet. – jaunt Sep 11 '15 at 19:52
  • @Paulie_D @jaunt I'm not using percentages in `transform-origin` though, I'm using pixels. – JKillian Sep 11 '15 at 19:53

3 Answers3

3

Newer versions of FF handle this more appropriately. Firefox 41 and up adds proper support for transform-origin with regards to SVG elements. It also adds the transform-box property. You can set this to view-box and it will use the SVG viewbox as a reference and correctly calculate the transform origin. FF 40 and older seem to calculate the position of the transform origin relative to the path element in question by default, and don't support any way to change this.

So good news for the future! However, this does not help with getting things working on the current version of FF or on IE.

JKillian
  • 18,061
  • 8
  • 41
  • 74
1

From @JKillian's answer there seem to be no way to fix it for older browsers.
There is another way to animate the element. :D
Im drawing to circle. No fill only stroke.
And animating the stroke to get the desired effect.

svg.spinner {
  display: block;
  width: 150px;
}
.circ {
  fill: none;
  stroke: #222;
  stroke-width: 10;
}
#circ2 {
  stroke: #999;
  stroke-dasharray: 160, 100;
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 2s;
}
svg:hover #circ2 {
  stroke-dashoffset: 500;
}
<svg class="spinner" viewBox="0 0 100 100">
  <circle class="circ" id="circ1" cx="50" cy="50" r="41" />
  <circle class="circ" id="circ2" cx="50" cy="50" r="41" />
</svg>
Persijn
  • 14,624
  • 3
  • 43
  • 72
  • Could this actually be used to get a full working solution? Either way, I like it... It's clever – JKillian Sep 11 '15 at 20:27
  • 1
    @JKillian if you just set an keyframe animation and then use from stroke-dashoffset from 0 to 500; You would have a working solution. If you hover you can see that its a working solution. – Persijn Sep 12 '15 at 14:59
1

This answer works on Firefox 40, Firefox 42 and Chrome.

svg.spinner {
  display: block;
  width: 50px;
}
svg.spinner path {
  fill-opacity: 0;
  stroke-width: 11;
}
svg.spinner path.track {
  stroke: rgba(92, 112, 128, 0.2);
}
svg.spinner path.head {
  stroke: rgba(92, 112, 128, 0.5);
  stroke-linecap: round;
  -ms-transform-origin: 50px 50px;
  transform-origin: 50px 50px;
  -webkit-animation: spin 2s linear infinite;
  animation: spin 2s linear infinite;
}
@-webkit-keyframes spin {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  to {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes spin {
  from {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }

  to {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
<svg class="spinner" viewBox="-50 -50 100 100">
  <g transform="translate(-50, -50)" >
  <path class="track" d="M 50,50 m 0,-44.5 a 44.5,44.5 0 1 1 0,89 a 44.5,44.5 0 1 1 0,-89"></path>
  <path class="head" d="M 91.81632162497291 65.21989637799226 A 44.5 44.5 0 0 0 50 5.5"></path>
  </g>
</svg>
Robert Longson
  • 118,664
  • 26
  • 252
  • 242