Cristian C
Cristian C

Reputation: 75

Animate SVG with CSS: first the stroke, then the fill

I'm completely new to animating SVGs with CSS (from what I've been reading, JS might also be needed to get the total path length) and need to achieve the following effect: http://gph.is/2iZZ3Hw

<?xml version="1.0" encoding="utf-8"?>
<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 47.4 47.7" style="enable-background:new 0 0 47.4 47.7;" xml:space="preserve">
<style type="text/css">
    .st0{fill-rule:evenodd;clip-rule:evenodd;fill:none;stroke:#FEC558;stroke-width:0.5;stroke-miterlimit:22.9256;}
    .st1{fill:#FFC656;}
</style>
<path class="st0" d="M23.7,45.8c12.1,0,22-9.9,22-22c0-12.1-9.9-22-22-22c-12.1,0-22,9.9-22,22C1.7,35.9,11.6,45.8,23.7,45.8z"/>
    <g>
        <polygon class="st1" points="14.1,17.9 14.1,20.2 14.1,22.2 14.1,23.4 14.1,24.7 14.1,27.6 32.7,35.2 32.7,32.5 32.7,30.7 
    32.7,29.7 32.7,28.5 32.7,25.2   "/>
        <polygon class="st1" points="19.2,18.7 24.3,20.6 27.5,21.9 27.5,21.2 27.5,19.4 27.5,17.5 27.5,16.3 27.5,15.2 27.5,12.5 
    15.5,17.2 19.2,18.7     "/>
    </g>
</svg>

Upvotes: 3

Views: 4448

Answers (2)

Alexandr_TT
Alexandr_TT

Reputation: 14545

SVG animation

<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"
width="30%" height="30%" viewBox="0 0 47.4 47.7" style="enable-background:new 0 0 47.4 47.7;" xml:space="preserve">
<style type="text/css">
    .st0{fill-rule:evenodd;clip-rule:evenodd;fill:none;stroke:#FEC558;stroke-width:0.5;stroke-miterlimit:22.9256;}
    .st1{fill:#FFC656;}
</style>
<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="0%" y2="100%" >
         
            <stop offset="0%" stop-color="#33363D"/>
            <stop offset="100%" stop-color="#5B5D5A"/>
</lineargradient>
</defs> 
<rect width="100%" height="100%" fill="url(#grad)"/>

<path id="circle" class="st0" stroke-dashoffset="138" stroke-dasharray="138" d="M23.7,45.8c12.1,0,22-9.9,22-22c0-12.1-9.9-22-22-22c-12.1,0-22,9.9-22,22C1.7,35.9,11.6,45.8,23.7,45.8z">
<animate id="an_circle" attributeName="stroke-dashoffset" values="138;0" dur="2s" fill="freeze" />
</path>
    <g stroke-width="0.5">
       <path id="trap" class="st1" stroke-dashoffset="60" stroke-dasharray="60" style="fill:none; stroke:#FEC558;" d="M14.1,17.9 14.1,20.2 14.1,22.2 14.1,23.4 14.1,24.7 14.1,27.6 32.7,35.2 32.7,32.5 32.7,30.7  32.7,29.7 32.7,28.5 32.7,25.2z">
        <animate id="an_trap" attributeName="stroke-dashoffset" values="60;0" dur="1s" fill="freeze" />
        <animate id="fill_trap" attributeName="fill" values="#33363D;#FEC558"  begin="an_circle.end" dur="1s" fill="freeze" />
     </path>
        <path id="triangle" class="st1" stroke-dashoffset="35" stroke-dasharray="35" style="fill:none; stroke:#FEC558;"  d="M19.2,18.7 24.3,20.6 27.5,21.9 27.5,21.2 27.5,19.4 27.5,17.5 27.5,16.3 27.5,15.2 27.5,12.5 15.5,17.2 19.2,18.7">
        
        <animate id="an_triangle" attributeName="stroke-dashoffset" begin="an_trap.end" values="35;0" dur="1s" fill="freeze" />
          <animate id="fill_triangle" attributeName="fill" values="#33363D;#FEC558"  begin="fill_trap.end-0.5s" dur="1s" fill="freeze" />
      </path>
    </g>
</svg>

  • Determine the length of objects using JS
    <script>
             function TotalLength(){
              var path = document.querySelector('#circle');
            var len = Math.round(path.getTotalLength() );
            alert("path length - " + len);
            };
      </script>

Path length:

for circle - 138px

for trapezium - 60px

for triangle - 35px

  • Command for drawing animation of objects
<animate id="an_circle" attributeName="stroke-dashoffset"
   values="138;0" dur="2s" fill="freeze" />
  <animate id="an_trap" attributeName="stroke-dashoffset"
     values="60;0" dur="1s" fill="freeze" />
<animate id="an_triangle" attributeName="stroke-dashoffset" 
   begin="an_trap.end" values="35;0" dur="1s" fill="freeze" />
  • The animation of drawing a triangle will begin when the animation of drawing of a trapezoid

begin="an_trap.end"

  • Animation fill color trapezium will begin when the animation is finished drawing a circle
<animate id="fill_trap" attributeName="fill" values="#33363D;#FEC558"  
    begin="an_circle.end" dur="1s" fill="freeze" />
  • An animation of the color filling of the triangle will begin when the fill animation of the trapezium ends
    <animate id="fill_triangle" attributeName="fill" values="#33363D;#FEC558"  
       begin="fill_trap.end-0.5s" dur="1s" fill="freeze" />

Upvotes: 9

Alexandr_TT
Alexandr_TT

Reputation: 14545

CSS solution

  • An animation for drawing shape outlines is implemented using CSS rules:

for the circle

.circle {
    fill:none;
    stroke:#FEC558;
    stroke-dashoffset:138.5;
    stroke-dasharray:138.5;
    animation: circle_stroke 2s ease-in forwards;
        } 

    @keyframes circle_stroke {
    0% {
    stroke-dashoffset: 138.5;
    }
    100% {
    stroke-dashoffset: 0;
      }
    }    
  • Animating the trapezium contour drawing and filling it with color

code below

.trap {
    stroke-dashoffset:60;
    stroke-dasharray:60;
        animation:trap_stroke 2s ease-in-out forwards,  trap_fill  ease-in 3s forwards;

    }

    @keyframes trap_stroke {
    0% {
    stroke-dashoffset: 60.5;
    }

      100% {
    stroke-dashoffset: 0;
      }
    }  

    @keyframes trap_fill {
    0% {
    fill: none;
    }

      100% {
    fill: #FEC558;
      }
    }    

Full animation code

 .trap, .triangle {
   stroke:#FEC558;
   stroke-width:0.5;
	fill:none;
   }
	
	.circle {
	fill:none;
	stroke:#FEC558;
	stroke-dashoffset:138.5;
	stroke-dasharray:138.5;
	animation: circle_stroke 2s ease-in forwards;
		} 
	
	@keyframes circle_stroke {
	0% {
   	stroke-dashoffset: 138.5;
	}
	100% {
   	stroke-dashoffset: 0;
	  }
	}
	

	
	
	.trap {
	stroke-dashoffset:60;
	stroke-dasharray:60;
		animation:trap_stroke 2s ease-in-out forwards,  trap_fill  ease-in 3s forwards;
	
	}
	
	@keyframes trap_stroke {
	0% {
   	stroke-dashoffset: 60.5;
	}
		  
	  100% {
   	stroke-dashoffset: 0;
	  }
	}  
	
	@keyframes trap_fill {
	0% {
   	fill: none;
	}
		  
	  100% {
   	fill: #FEC558;
	  }
	}  


	.triangle {
	stroke-dashoffset:35.5;
	stroke-dasharray:35.5;
	
	animation: triangle_stroke 1s ease-in-out forwards, triangle_fill 3.5s ease-in forwards;
	}  
	
	@keyframes triangle_stroke {
	0% {
   	stroke-dashoffset: 35.5;
	}
	100% {
   	stroke-dashoffset: 0;
	  }
	}  
	
	@keyframes triangle_fill {
	0% {
   	fill: none;
	}
	100% {
   	fill: #FEC558;;
	  }
	}
	
<?xml version="1.0" encoding="utf-8"?>
<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"
width="30%" height="30%" viewBox="0 0 47.4 47.7" style="enable-background:new 0 0 47.4 47.7;" xml:space="preserve">  

<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="0%" y2="100%" >
         
            <stop offset="0%" stop-color="#33363D"/>
            <stop offset="100%" stop-color="#5B5D5A"/>
</lineargradient>
</defs> 
<rect width="100%" height="100%" fill="url(#grad)"/>

<path class="circle" d="M23.7,45.8c12.1,0,22-9.9,22-22c0-12.1-9.9-22-22-22c-12.1,0-22,9.9-22,22C1.7,35.9,11.6,45.8,23.7,45.8z"/>

    
       <path class="trap"    d="M14.1,17.9 14.1,20.2 14.1,22.2 14.1,23.4 14.1,24.7 14.1,27.6 32.7,35.2 32.7,32.5 32.7,30.7  32.7,29.7 32.7,28.5 32.7,25.2z" />
       	  
        <path class="triangle"   d="M19.2,18.7 24.3,20.6 27.5,21.9 27.5,21.2 27.5,19.4 27.5,17.5 27.5,16.3 27.5,15.2 27.5,12.5 15.5,17.2 19.2,18.7"/>
	

</svg>

DEMO

UPD

Works in all modern browsers, except IE

"IE10 and IE11 do not support CSS keyframe blocks inside media queries."

(see the "Known Issues")

Upvotes: 2

Related Questions