-->

Animate an SVG object that uses SVG sprite icon

2019-09-06 18:12发布

问题:

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     ---------------------------------  -->

回答1:

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>



回答2:

Thanks Paul LeBeau!! My problem was that I have placed the 'class' attribute on my icon 'path' tag. Because of that I could not modify them after creation, when I removed the 'class' I was able to change the css on a higher level tag. This way I was able to still reuse the icon with sprites, without duplicating code.

So to recap: if we need to modify specific paths inside the icon, we cannot use this technique with sprites. Hope that helps someone :)

$('#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 style="display:none;">
  <symbol id="icon_1" viewBox="0 0 54 54">
    <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>
</svg>

<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)">
    <use xlink:href="#icon_1"></use>
  </g>
</svg>