0

I have an SVG path for an arrow created in Illustrator, but I can't for the life of me figure out how (or if I can) animate it the way I want to. Below is the closest I've come, but as you can tell...just not there.

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 850 683" style="enable-background:new 0 0 792 612;" xml:space="preserve">

<linearGradient id="lg" x1="0.5" y1="1" x2="0.5" y2="0">
          <stop offset="0%" stop-opacity="1" stop-color="#fff"></stop>
          <stop offset="0.29" stop-opacity="1" stop-color="#fff">
            <animate attributeName="offset" values="1;0;1" repeatCount="indefinite" dur="10s" begin="0s"></animate>
          </stop>
          <stop offset="0.29" stop-opacity="0" stop-color="#fff">
            <animate attributeName="offset" values="1;0;1" repeatCount="indefinite" dur="10s" begin="0s"></animate>
          </stop>
          <stop offset="100%" stop-opacity="0" stop-color="royalblue"></stop>
      </linearGradient>

<path class="st4 arrow" fill="url(#lg" d="M500.3,201.9l-33.7,17.5l10.1,6.4l-71,111.4l-39.9-62.3c0,0,0,0-0.1-0.1c-0.1-0.2-0.3-0.4-0.5-0.6
 c-0.1-0.2-0.3-0.3-0.4-0.5c-0.1-0.1-0.3-0.3-0.4-0.4c-0.2-0.2-0.4-0.4-0.7-0.5c0,0,0,0-0.1-0.1c-0.1-0.1-0.3-0.1-0.4-0.2
 c-0.2-0.1-0.5-0.3-0.7-0.4c-0.2-0.1-0.4-0.2-0.7-0.2c-0.2-0.1-0.4-0.1-0.6-0.2c-0.2,0-0.5-0.1-0.7-0.1c-0.2,0-0.4,0-0.6,0
 c-0.2,0-0.5,0-0.7,0.1c-0.2,0-0.4,0-0.7,0.1c-0.2,0-0.5,0.1-0.7,0.2c-0.2,0.1-0.4,0.1-0.6,0.2c-0.3,0.1-0.5,0.2-0.8,0.4
 c-0.1,0.1-0.3,0.1-0.4,0.2c0,0,0,0-0.1,0.1c-0.2,0.2-0.5,0.3-0.7,0.5c-0.1,0.1-0.3,0.2-0.4,0.4c-0.1,0.1-0.3,0.3-0.4,0.5
 c-0.2,0.2-0.3,0.4-0.5,0.6c0,0,0,0-0.1,0.1l-72.8,113c-2.1,3.3-1.2,7.6,2.1,9.7c1.2,0.8,2.5,1.1,3.8,1.1c2.3,0,4.6-1.1,5.9-3.2
 l66.8-103.7l39.9,62.4c0,0,0,0,0.1,0.1c0.3,0.5,0.6,0.9,1,1.2c0.1,0.1,0.2,0.2,0.3,0.3c0.2,0.2,0.4,0.4,0.7,0.5
 c0.1,0,0.1,0.1,0.2,0.1c0.4,0.2,0.8,0.4,1.2,0.5c0.2,0.1,0.4,0.2,0.6,0.2c0.5,0.1,1.1,0.2,1.7,0.2c0,0,0.1,0,0.1,0
 c0.6,0,1.2-0.1,1.8-0.3c0.2,0,0.3-0.1,0.5-0.2c0.4-0.2,0.9-0.3,1.3-0.6c0.1,0,0.1,0,0.2-0.1c0.2-0.1,0.4-0.3,0.6-0.5
 c0.1-0.1,0.3-0.2,0.4-0.3c0.4-0.4,0.7-0.8,1-1.2c0,0,0.1-0.1,0.1-0.1l77-120.7l10.1,6.4L500.3,201.9z"></path>

</svg>

Basically I just want to the animation to look like the arrow is drawn on from left to right...and I'm not that close :/ can anyone help??

https://jsfiddle.net/cnilsson/g4wfpmr9/

nilssonc
  • 29
  • 6
  • https://css-tricks.com/svg-line-animation-works/ – CBroe Aug 07 '17 at 11:31
  • I've come across this article a number of times in searching both on my own and through stackoverflow, but my issue is that using the stroke animation, it just draws the outline of the arrow, and doesn't have anything to do with the fill. Unless there's way to re-draw the path of the arrow so it's just one solid line rather than a shape or something? – nilssonc Aug 07 '17 at 11:54
  • Do you want the arrow-head to move and draw the line behind it? If so my first thoughts would be to use a marker https://developer.mozilla.org/en/docs/Web/SVG/Element/marker for the arrowhead, then animate that and the line (using the dash-offset trick) at the same time. Good luck. – Ruskin Aug 07 '17 at 12:23
  • I did something similar in https://stackoverflow.com/a/42626643/581414 – Ruskin Aug 07 '17 at 12:29
  • That's a good thought, I could try that....thanks. I probably wouldn't want to lead with the arrow, more like a fill from bottom to top. – nilssonc Aug 07 '17 at 12:32

2 Answers2

2

Another approach would be to animate the path data itself. This has its obvious limitations in the number of vertices the path has. The longer the list, the more unmanageable it gets. Reversing the animation means doubling the value list. For a proper start and end, set the d on the path element itself to the first/last animated value.

For the arrowhead, it must be moved along, and to always have it point into the right direction, you need to add extra intermediate animation points. Note that there are intermediate keyTimes that are doubled.

To let everything disapear at the end of the animation the arrowhead needs to shown only during the duration of the animation.

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="250">
  <defs>
    <marker orient="auto" refY="0" refX="0" id="tri" style="overflow:visible">
      <path d="M 1.76,0 -0.56,1.36 V -1.36 Z" fill="royalblue" />
    </marker>
  </defs>
  <path d="M 47,213 47,213 47,213 47,213"
        fill="none" stroke="royalblue" stroke-width="14"
        stroke-linejoin="round" marker-end="none">
    <animate attributeType="XML" attributeName="d" 
             begin="0s" dur="10s" fill="remove"
             keyTimes="0;0.18;0.18;0.27;0.27;0.45;0.55;0.73;0.73;0.82;0.82;1"
             values="M 47,213 47,213 47,213 47,213;
                     M 47,213 47,213 47,213 120,100;
                     M 47,213 120,100 120,100 120,100;
                     M 47,213 120,100 120,100 166,171;
                     M 47,213 120,100 166,171 166,171;
                     M 47,213 120,100 166,171 247,44;
                     M 47,213 120,100 166,171 247,44;
                     M 47,213 120,100 166,171 166,171;
                     M 47,213 120,100 120,100 166,171;
                     M 47,213 120,100 120,100 120,100;
                     M 47,213 47,213 47,213 120,100;
                     M 47,213 47,213 47,213 47,213" />
    <set attributeType="CSS" attributeName="marker-end"
         begin="0s" dur="10s" to="url(#tri)" />
  </path>
</svg>
ccprog
  • 20,308
  • 4
  • 27
  • 44
  • This is awesome, that may do it. I don't mind leading with the arrow, just depends on the client's preference, so we'll see what they think. One quick question: is there a way to reverse the animation? Possibly pause it for a second once it reaches the top, and then reverse it? That may be too much to ask, not sure....I'm new to SVG and trying to learn/figure it all out. – nilssonc Aug 07 '17 at 16:11
  • see edit - reversing here only works by doubling the value list. – ccprog Aug 07 '17 at 16:53
  • This is great! Thank you so much! Last question...so I've added this arrow into the project/logo it's part of and tinkered with some of the values to position it and match it where I need to...but still running into issues with the state before and after the animation. See this link: https://sandbox.nilssonweb.co.uk/svg-test/ You'll notice that before it goes, it loads like it's halfway through, and after it's finished, it goes back to that state. How do I get it to start from the ground up and disappear at finish? – nilssonc Aug 08 '17 at 15:33
  • edited - note the `d` value of path and the extra `` animation. – ccprog Aug 08 '17 at 15:53
  • This has been EXTREMELY helpful so far - thank you so much for the help ccprog. One last question.... After the animation ends, I need it to play one more time, but then have the arrow stay in place. Rather than add to the existing, I've just duplicated it so a second one runs on a delay. The only issue I'm having is that the second arrow appears in full before the animation plays, and I need it to start from nothing. The updated fiddle is below, and hopefully it will make more sense. https://jsfiddle.net/cnilsson/g4wfpmr9/1/ – nilssonc Aug 15 '17 at 09:13
  • 1. Use only one path, but duplicate the animations as its sub-elements. 2. `dur=".9"` is illegal syntax, use `dur="0.9"` 3. Read up on the `` [attribute](https://www.w3.org/TR/smil-animation/#Fill) – ccprog Aug 15 '17 at 11:51
0

You could just change your gradient so that it goes from left to right, rather than bottom to top. Perhaps that is good enough for your needs?

body {
  background-color: grey;
}
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 850 683" style="enable-background:new 0 0 792 612;" xml:space="preserve">

<linearGradient id="lg" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0%" stop-opacity="1" stop-color="#fff"></stop>
          <stop offset="0.29" stop-opacity="1" stop-color="#fff">
            <animate attributeName="offset" values="0;1;0" repeatCount="indefinite" dur="5s" begin="0s"></animate>
          </stop>
          <stop offset="0.29" stop-opacity="0" stop-color="#fff">
            <animate attributeName="offset" values="0;1;0" repeatCount="indefinite" dur="5s" begin="0s"></animate>
          </stop>
          <stop offset="100%" stop-opacity="0" stop-color="royalblue"></stop>
      </linearGradient>
      
      <path class="st4 arrow" fill="url(#lg)" d="M500.3,201.9l-33.7,17.5l10.1,6.4l-71,111.4l-39.9-62.3c0,0,0,0-0.1-0.1c-0.1-0.2-0.3-0.4-0.5-0.6
 c-0.1-0.2-0.3-0.3-0.4-0.5c-0.1-0.1-0.3-0.3-0.4-0.4c-0.2-0.2-0.4-0.4-0.7-0.5c0,0,0,0-0.1-0.1c-0.1-0.1-0.3-0.1-0.4-0.2
 c-0.2-0.1-0.5-0.3-0.7-0.4c-0.2-0.1-0.4-0.2-0.7-0.2c-0.2-0.1-0.4-0.1-0.6-0.2c-0.2,0-0.5-0.1-0.7-0.1c-0.2,0-0.4,0-0.6,0
 c-0.2,0-0.5,0-0.7,0.1c-0.2,0-0.4,0-0.7,0.1c-0.2,0-0.5,0.1-0.7,0.2c-0.2,0.1-0.4,0.1-0.6,0.2c-0.3,0.1-0.5,0.2-0.8,0.4
 c-0.1,0.1-0.3,0.1-0.4,0.2c0,0,0,0-0.1,0.1c-0.2,0.2-0.5,0.3-0.7,0.5c-0.1,0.1-0.3,0.2-0.4,0.4c-0.1,0.1-0.3,0.3-0.4,0.5
 c-0.2,0.2-0.3,0.4-0.5,0.6c0,0,0,0-0.1,0.1l-72.8,113c-2.1,3.3-1.2,7.6,2.1,9.7c1.2,0.8,2.5,1.1,3.8,1.1c2.3,0,4.6-1.1,5.9-3.2
 l66.8-103.7l39.9,62.4c0,0,0,0,0.1,0.1c0.3,0.5,0.6,0.9,1,1.2c0.1,0.1,0.2,0.2,0.3,0.3c0.2,0.2,0.4,0.4,0.7,0.5
 c0.1,0,0.1,0.1,0.2,0.1c0.4,0.2,0.8,0.4,1.2,0.5c0.2,0.1,0.4,0.2,0.6,0.2c0.5,0.1,1.1,0.2,1.7,0.2c0,0,0.1,0,0.1,0
 c0.6,0,1.2-0.1,1.8-0.3c0.2,0,0.3-0.1,0.5-0.2c0.4-0.2,0.9-0.3,1.3-0.6c0.1,0,0.1,0,0.2-0.1c0.2-0.1,0.4-0.3,0.6-0.5
 c0.1-0.1,0.3-0.2,0.4-0.3c0.4-0.4,0.7-0.8,1-1.2c0,0,0.1-0.1,0.1-0.1l77-120.7l10.1,6.4L500.3,201.9z"></path>

</svg>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • Aha...that may just do it. It might even need to be sped up a bit so it looks a little less like it's just being "revealed" and more being drawn. Depends on how the client likes it really, so I guess we'll see. Thank you so much though, I'm new to SVG stuff and I coudln't for the life of me figure out how to switch the direction. – nilssonc Aug 07 '17 at 16:10