Search code examples
svgvelocity.js

Animate an SVG object that uses SVG sprite icon


I have an SVG sprite that contains 2 symbols, the second symbol uses the first one. I need to separate this into sprites, because i use the icons more then once.

my problem is that i cannot animate the object the way i need, hope that someone can help. Basically its a button with an icon, once i click it, i change the scale in 20% + animate the color transition and the stroke transition to different colors. Currently i managed to reference the various symbol parts with jquery, i dont think its the right way as i understand its suppose to be an independent object.

Basically i need the button to scale + transit color fill + transit color stroke on click.

$('#shape2').on('click', function(a, v, b) {

  $(this).velocity({
    scale: 0.99,
    duration: 100,
    complete: function() {
      $(this).velocity({
        scale: 1.4
      }, {
        duration: 1000
      });
       //i don't want to do this, i want to access it as an object (this), but i cannot
      $("#icon_2").find('circle').velocity({
        fill: '#00b2ff',
        duration: 1000,
        complete: function() {
          $("#icon_1").find("path").velocity({
            stroke: "#fff",
            queue: false
          }, 1000);
        }
      });
    }
  });
})
.st0 {
  fill: none;
  stroke: #0083ED;
  stroke-miterlimit: 5;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.2/velocity.js"></script>
<svg width="0" height="0">
  <defs>
    <symbol id="icon_1" viewBox="0 0 50 50" class="st0">
      <path d="M10.6 29.3h14.5V44H10.6z" />
      <path d="M25 29.3h14.5V44H25zm-7.2-14.7h14.5v14.7H17.8zm0 0l3.9-4m10.6 4l3.9-4m-3.9 18l3.9-3.7m-25.6 4.4l4.3-4.4m24.6 4.7l3.9-4M39.5 44l3.9-4M21.2 10.6h15M14.5 24.9h3.3m17.7.6h7.9M36.2 10v15.5m7.2.1V40" />
    </symbol>
    <symbol id="icon_2">
      <circle cx="50" cy="50" r="48" fill="#dcf2f8" stroke="white" stroke-width="2" />
      <use x="7" y="5" width="80" height="80" xlink:href="#icon_1"></use>
    </symbol>
  </defs>
</svg>


<!--                s     v         g     ---------------------------------  -->


<svg width='100' height='100' id="shape2">
  <use xlink:href="#icon_2"></use>
</svg>
<!--                s     v         g     ---------------------------------  -->


Solution

  • Symbols are intended to be predefined then get reused as is. You can't define a symbol and create differing instances of it. Or to say it another way, you can't restyle the same symbol in more than one way.

    So if you may be using the same symbol more than once on the page, then symbols won't be what you want.

    If you forgo symbols, then you can achieve what you want using something like the following.

    $('#shape2').on('click', function(a, v, b) {
    
      $this = $(this);
      // Animate the SVG's size. Since it has a viewBox, everything inside gets scaled too
      $this.velocity({scale: 1.4, duration: 1000});
      // Animate the icon colours
      $this.find("circle").velocity({fill: '#00b2ff'});
      $this.find(".st0").velocity({stroke: "#fff"});
    
    })
    .st0 {
      fill: none;
      stroke: #0083ED;
      stroke-miterlimit: 5;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.2/velocity.js"></script>
    
    <svg width='100' height='100' id="shape2" viewBox="0 0 50 50">
      <circle cx="25" cy="25" r="24" fill="#dcf2f8" stroke="white" stroke-width="2" />
      <g class="st0" transform="translate(3.5, 2.5) scale(0.8)">
        <path d="M10.6 29.3h14.5V44H10.6z" />
        <path d="M25 29.3h14.5V44H25zm-7.2-14.7h14.5v14.7H17.8zm0 0l3.9-4m10.6 4l3.9-4m-3.9 18l3.9-3.7m-25.6 4.4l4.3-4.4m24.6 4.7l3.9-4M39.5 44l3.9-4M21.2 10.6h15M14.5 24.9h3.3m17.7.6h7.9M36.2 10v15.5m7.2.1V40" />
      </g>
    </svg>