Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to efficiently reverse SVG (SMIL) Animation on Motion Path?

I am trying to determine how to efficiently reverse this SVG animation (with SMIL) which uses animateMotion and the d attribute on the path element. I need the animation to run counterclockwise around the shape.

The current animation can be found here and the relevant code is as follows.

document.getElementById("svgobject").pauseAnimations();
<svg version="1.1" id="svgobject" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="451.5px" height="451.5px" viewBox="0 0 461.5 461.5" enable-background="new 0 0 461.5 461.5" xml:space="preserve">
  <g>
    <path fill="none" stroke="black"
          d="M446.85,280.187c0,30.296-24.56,54.854-54.854,54.854H60.239c-30.296,0-54.854-24.559-54.854-54.854l0,0c0-30.296,24.559-54.854,54.854-54.854h331.756C422.29,225.333,446.85,249.891,446.85,280.187L446.85,280.187z"/>
    <rect id="rect" x="0" y="0" width="50" height="20" fill="gray" stroke="black" stroke-width="1" transform="translate(-25, -10)">
      <animateMotion path="M446.85,280.187c0,30.296-24.56,54.854-54.854,54.854H60.239c-30.296,0-54.854-24.559-54.854-54.854l0,0c0-30.296,24.559-54.854,54.854-54.854h331.756C422.29,225.333,446.85,249.891,446.85,280.187L446.85,280.187z"
        begin= "0s" dur="2s" repeatCount="1" rotate="auto" fill="freeze" />
    </rect>
  </g>

  <!--start and stop animation-->
  <g onclick="document.getElementById('svgobject').unpauseAnimations()"
     transform="translate(160 100)">
    <rect width="60" height="30" rx="10" stroke="black" fill-opacity="0.2"/>
    <text style="font: 16px Arial Black; fill: white; stroke: black;"
          transform="translate(2 20)">START</text>
  </g>
  <g onclick="document.getElementById('svgobject').pauseAnimations()"
     transform="translate(260 100)">
    <rect width="60" height="30" rx="10" stroke="black" fill-opacity="0.2"/>
    <text style="font: 16px Arial Black; fill: white; stroke: black;"
          transform="translate(5 20)">STOP</text>
  </g>
</svg>

I understand that I can manually reverse the SVG path data commands including moveto (M,m), lineto (L,l), curveto (C,c), etc.

Given the amount of path coordinates that I'll need to reverse (in addition to those in this animation), I'm trying to determine if there is a more efficient way to do this.

like image 411
jjdewitt Avatar asked Jan 21 '15 00:01

jjdewitt


1 Answers

You can reverse the direction of your animation by using the keyPoints and keyTimes attributes.

<animateMotion path="..." begin= "0s" dur="2s" repeatCount="1" rotate="auto"
               fill="freeze" keyPoints="1;0" keyTimes="0;1">

Here we are telling the motion to run from 1 (end of the path) to 0 (start of the path).

This works in Firefox, but unfortunately not in Chrome. It seems Chrome is bugged.

Update:

I found the Chrome bug related to this: https://code.google.com/p/chromium/issues/detail?id=353108

It seems keyTimes is broken if the calcMode is "paced" (which it defaults to). If you change it to something else, like "linear: the animation works correctly in Chrome also.

<animateMotion path="..." begin= "0s" dur="2s" repeatCount="1" rotate="auto"
               fill="freeze" keyPoints="1;0" keyTimes="0;1" calcMode="linear">

Demo here

Updated Codepen here

like image 122
Paul LeBeau Avatar answered Sep 18 '22 22:09

Paul LeBeau