svgsvg-animateinline-svg

SVG Animated Graph Arrow


This is my first time using SVG and I want to know if it is possible to create an animated line graph with an arrow. I have found multiple examples of animated line graphs without arrows, non-animated line graphs with arrows, and animated straight lines with arrows, but not exactly what I am looking for. I have attached some codepen examples I've been playing around with below. Does anyone know if this is possible/have a solution? It would be greatly appreciated!

  1. Animated line missing arrow (needs arrow): http://codepen.io/alexandraleigh/pen/jVaObd

    # HTML
    <div class="graph__wrapper">
      <svg width="315px" height="107px" viewBox="0 0 315 107" version="1.1">
        <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
          <path d="M2.10546875,95.75 L40.5546875,68.3476562 L55.2109375,81.1796875 L65.2148437,76.3945312 L96.1835937,86.8320312 L131.023438,19.9414062 L142.15625,23.7226562 L183.605469,2.1953125 L211.007812,22.3320312 L234.320312,71.5664062 L234.667969,83.0039062 L244.019531,83.0039062 L247.105469,88.8320312 L312.695312,104.839844" id="Path-1" stroke="white" stroke-width="4" sketch:type="MSShapeGroup" class="path"></path>
        </g>
      </svg>
    </div> 
    
    
    # CSS(Less)
    
    @import "lesshat";
    
    @darkgrey:          #303030;
    
    *{
      box-sizing: border-box;
    }
    
    body{
      background: @darkgrey;
    }
    
    .graph__wrapper{
      width: 400px;
      margin: 30px auto;
      position: relative;
    
      svg{
        position: absolute;
        margin: 36px 0px 0px 15px;
      }
    }
    
    .path {
      stroke-dasharray: 1000;
      stroke-dashoffset: 1000;
      animation: dash 3s ease-in forwards;
      animation-iteration-count: 1;
      animation-delay: 1s;
    }
    
    @keyframes dash {
      to {
        stroke-dashoffset: 0;
      }
    }
    
    .description{
      font-family: "Roboto";
      color:lighten(@darkgrey, 50%);
      text-align: center;
      margin: 40px 0px;
    } 
    
  2. Animated straight line with arrow (needs to stop at multiple points on path): http://codepen.io/alexandraleigh/pen/yVPYrY

  3. I tried adding the path descriptions from #1 to #2 and it has the desired final graph, just no animations: http://codepen.io/alexandraleigh/pen/pNdgWR

  4. I also tried adding the arrow marker from #2 to #1, but the arrow doesn't animate: http://codepen.io/alexandraleigh/pen/aBVdVY

I'm also open to using a plugin such as http://snapsvg.io/, but haven't seen any working examples that help my situation.


Solution

  • you can do this with offset-motion(old syntax: motion-path). Be aware that this is a heighly experimental feature. it currently only works in Chrome. More to the point i use the "old" syntax here as that is what currently works in chrome, but it will soon switch to the new systax...

    * {
      box-sizing: border-box;
    }
    body {
      background: #303030;
    }
    .graph__wrapper {
      width: 400px;
      margin: 30px auto;
      position: relative;
      svg {
        position: absolute;
        margin: 36px 0px 0px 15px;
      }
    }
    .path {
      stroke-dasharray: 428;
      stroke-dashoffset: 428;
      animation: dash 3s ease-in forwards;
      animation-iteration-count: 1;
      animation-delay: 1s;
    }
    @keyframes dash {
      to {
        stroke-dashoffset: 0;
      }
    }
    @keyframes pm {
      from {
        motion-offset: 0%;
      }
      to {
        motion-offset: 100%
      }
    }
    #arrow {
      animation: pm 3s ease-in forwards;
      animation-iteration-count: 1;
      animation-delay: 1s;
      motion-path: path('M2.10546875,95.75 L40.5546875,68.3476562 L55.2109375,81.1796875 L65.2148437,76.3945312 L96.1835937,86.8320312 L131.023438,19.9414062 L142.15625,23.7226562 L183.605469,2.1953125 L211.007812,22.3320312 L234.320312,71.5664062 L234.667969,83.0039062 L244.019531,83.0039062 L247.105469,88.8320312 L312.695312,104.839844');
      motion-rotation: auto;
      motion-anchor: center;
    }
    .description {
      font-family: "Roboto";
      color: lighten(@darkgrey, 50%);
      text-align: center;
      margin: 40px 0px;
    }
    <div class="graph__wrapper">
      <svg width="315px" height="107px" viewBox="0 0 315 107" version="1.1" style="overflow:visible">
        <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
          <path d="M2.10546875,95.75 L40.5546875,68.3476562 L55.2109375,81.1796875 L65.2148437,76.3945312 L96.1835937,86.8320312 L131.023438,19.9414062 L142.15625,23.7226562 L183.605469,2.1953125 L211.007812,22.3320312 L234.320312,71.5664062 L234.667969,83.0039062 L244.019531,83.0039062 L247.105469,88.8320312 L312.695312,104.839844"
          id="Path-1" stroke="white" stroke-width="4" sketch:type="MSShapeGroup" class="path"></path>
    
    
    
          <polyline id="arrow" points="0,-5 10,0 0,5 1,0" fill="white" />
    
        </g>
      </svg>
    </div>

    you can also do this with animateMotion, but svg animations are soon to be depricted. You will have to rewrite your code in any way sooner or later :-(

    * {
      box-sizing: border-box;
    }
    body {
      background: #303030;
    }
    .graph__wrapper {
      width: 400px;
      margin: 30px auto;
      position: relative;
      svg {
        position: absolute;
        margin: 36px 0px 0px 15px;
      }
    }
    .path {
      stroke-dasharray: 428;
      stroke-dashoffset: 428;
      animation: dash 3s linear forwards;
      animation-iteration-count: 1;
      animation-delay: 1s;
    }
    @keyframes dash {
      to {
        stroke-dashoffset: 0;
      }
    }
    .description {
      font-family: "Roboto";
      color: lighten(@darkgrey, 50%);
      text-align: center;
      margin: 40px 0px;
    }
    <div class="graph__wrapper">
      <svg width="315px" height="107px" viewBox="0 0 315 107" version="1.1" style="overflow:visible">
        <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
          <path d="M2.10546875,95.75 L40.5546875,68.3476562 L55.2109375,81.1796875 L65.2148437,76.3945312 L96.1835937,86.8320312 L131.023438,19.9414062 L142.15625,23.7226562 L183.605469,2.1953125 L211.007812,22.3320312 L234.320312,71.5664062 L234.667969,83.0039062 L244.019531,83.0039062 L247.105469,88.8320312 L312.695312,104.839844"
          id="Path-1" stroke="white" stroke-width="4" sketch:type="MSShapeGroup" class="path"></path>
    
    
    
          <polyline id="arrow" points="0,-5 10,0 0,5 1,0" fill="white">
            <animateMotion rotate="auto" begin="1s" dur="3s" repeatCount="1" fill="freeze">
              <mpath xlink:href="#Path-1" />
            </animateMotion>
          </polyline>
    
        </g>
      </svg>
    </div>