Jordan Mann
Jordan Mann

Reputation: 477

Strange Safari behavior with multiple SVG <animate>'s

I am attempting to animate an SVG play-stop button with multiple <animate> tags on a polygon, such that running beginElement() on each <animate> would cause the shape to morph its points. This works great in Chrome and Firefox, but, when testing in Safari, I only seem to be able to activate one <animate> tag.

The what I currently have is as follows:

playState = true;

function toggle() {
  playState = !playState;
  document.querySelector("#to" + (playState ? "Play" : "Stop")).beginElement();
  console.log("Changed state to " + (playState ? "play" : "stop") + ".")
}

document.querySelector("#toggle").addEventListener("click", toggle);

toggle();
#toggle circle {
  fill: #808080;
}

#toggle polygon {
  fill: #DCDCDC;
}
<svg id="toggle" viewBox="0 0 300 300">
        <circle cx="150" cy="150" r="100"/>

<polygon points="150,150 150,150 150,150 150,150">
    <animate fill="freeze" id="toStop" attributeName="points" dur="500ms" to="100,100 100,200 200,200 200,100" begin="indefinite"     calcMode      = "spline"
    keySplines    = "0 0.75 0.25 1"
    keyTimes      = "0;1"/>
     <animate fill="freeze" id="toPlay" attributeName="points" dur="500ms" to="120,100 120,200 206.6025403784,150 206.6025403784,150" begin="indefinite"     calcMode      = "spline"
    keySplines    = "0 0.75 0.25 1"
    keyTimes      = "0;1"/>
    </polygon>

</svg>

Testing in Safari, I can correctly fire #toPlay initially, but, afterwards, running beginElement() on #toPlay flickers between the two states and activating #toStop does nothing. It is almost as though the #toStop animation is being delayed, and then is running rapidly when #toPlay is fired again.

Upvotes: 2

Views: 382

Answers (1)

Jordan Mann
Jordan Mann

Reputation: 477

I figured it out on my own! However, I was forced to compromise slightly. Jesus CMD explains that you need to reset the SVG animation on every other call to beginElement(). The downside of this solution is that the animation must be reset to the polygon points' intial value, so my hopes of having three possible polygon shapes (a single point, a square, and a triangle) must be narrowed down to only two states: play and stop.

The changed snippet is below.

playState = true;
svg = document.querySelector("#toggle");

function toggle() {
  playState = !playState;
  if (playState) {

    svg.pauseAnimations();
    svg.setCurrentTime(0);
    svg.unpauseAnimations();
    document.querySelector("#toPlay").beginElement();
  } else {
    document.querySelector("#toStop").beginElement();
  }
  //document.querySelector("#to" + (playState ? "Play" : "Stop")).beginElement();
  console.log("Changed to " + (playState ? "Play" : "Stop"))
}

svg.addEventListener("click", toggle);
toggle();
#toggle circle {
  fill: #808080;
}

#toggle polygon {
  fill: #DCDCDC;
}
<svg id="toggle" viewBox="0 0 300 300">
        <circle cx="150" cy="150" r="100"/>

<polygon points="100,100 100,200 200,200 200,100">
    <animate fill="freeze" id="toStop" attributeName="points" dur="500ms" to="100,100 100,200 200,200 200,100" begin="indefinite"     calcMode      = "spline"
    keySplines    = "0 0.75 0.25 1"
    keyTimes      = "0;1"/>
     <animate fill="freeze" id="toPlay" attributeName="points" dur="500ms" to="120,100 120,200 206.6025403784,150 206.6025403784,150" begin="indefinite"     calcMode      = "spline"
    keySplines    = "0 0.75 0.25 1"
    keyTimes      = "0;1"/>
    </polygon>

</svg>

Upvotes: 4

Related Questions