Alexandr_TT
Alexandr_TT

Reputation: 14585

How to create an animated stackoverflow icon

Below my code icons:

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240" viewBox="0 0 120 120">
  <style>.st0{fill:#bcbbbb}.st1{fill:#f48023}  </style>
  <path class="st0" d="M84.4 93.8V70.6h7.7v30.9H22.6V70.6h7.7v23.2z"/>
  <path class="st1" d="M38.8 68.4l37.8 7.9 1.6-7.6-37.8-7.9-1.6 7.6zm5-18l35 16.3 3.2-7-35-16.4-3.2 7.1zm9.7-17.2l29.7 24.7 4.9-5.9-29.7-24.7-4.9 5.9zm19.2-18.3l-6.2 4.6 23 31 6.2-4.6-23-31zM38 86h38.6v-7.7H38V86z"/>
</svg>

Animation Script:

  1. Cart outline drawing animation
  2. Fill the outline color with a basket
  3. Sequential animation of the appearance of 5 color stripes
  4. Strips disappear in the reverse order.
  5. Looping appearance, disappearance of colored stripes.

Here is my attempt:

<svg id="svg1" xmlns="http://www.w3.org/2000/svg" width="240" height="240" viewBox="0 0 120 120" style="border:1px solid;">
  <style>
    .st0{fill:white; stroke:#BCBBBB; stroke-width:2;}
	.st1{fill:#f48023;opacity:1;}

  </style>
  <path class="st0"  d="M84.4 93.8V70.6h7.7v30.9H22.6V70.6h7.7v23.2z" stroke-dasharray="0,123.5 0,123.5" stroke-dashoffset="150"> 
        <!-- Cart outline drawing animation -->
     <animate id="bask" attributename="stroke-dasharray" dur="4s" begin="svg1.click" values="0,123.5 0,123.5;0,0,247,0" fill="freeze" />  
	     <!--  Filling  baskets of the icon color -->
	   <animate id="bask_fill"  attributename="fill" dur="1s" begin="bask.end" values="white;#BCBBBB" fill="freeze" />
  </path>   
  
  <path class="st1"  d="M38 86H76.6V78.3H38V86Z">
    <animateTransform attributeName="transform" type="rotate" begin="bask_fill.end" dur="4s" values="0 100 100;45 100 100;0 100 100" repeatCount="indefinite" />
   </path>	

<text x="30" y="115" font-size="14px" fill="#BCBBBB" >Click me</text>    
   </svg>

I want the colored stripes to appear one after another and after the last strip appear they should disappear in the reverse order.
I did not succeed in applying rotation to solve this problem.

Any help for a solution would be very appreciated.

Upvotes: 1

Views: 405

Answers (2)

Alexandr_TT
Alexandr_TT

Reputation: 14585

First, I'll start to realize the animation of the icon from 3 to 5 point of the script in the question

  1. The appearance of the color bar - animation from opacity: 0; to opacity:1;

  2. The animation disappearance of the color bars of the opacity to 0

  3. then after the end of one cycle of appearance, disappearance, a repeat of the process will begin

begin="svg1.click;Back5.end+1.5s"

Please read the comments in the code

<svg id="svg1" xmlns="http://www.w3.org/2000/svg" width="240" height="240" viewBox="0 0 120 120" style="border:1px solid;">
  <style>
    .st0{fill:#bcbbbb}.st1{fill:#f48023;opacity:0;}

  </style>
  <path class="st0"  d="M84.4 93.8V70.6h7.7v30.9H22.6V70.6h7.7v23.2z">
  </path>   
  
  <path class="st1"  d="M38 86H76.6V78.3H38V86Z"> 
           <!-- 3.   Animation of the appearance of the first color strip -->
       <animate id="an1" attributeName="opacity" to="1" dur="0.001s" begin="svg1.click;Back5.end+1.5s" fill="freeze" />  
            <!-- 4. The animation disappearance of the color bars of the opacity to 0 -->
         <animate id="Back1" attributeName="opacity" to="0" dur="0.001s" begin="Back2.end+0.125s" fill="freeze" />
    </path>   
  <path class="st1" d="M38.8 68.4L76.6 76.3 78.2 68.7 40.4 60.8 38.8 68.4Z" >
      <animate id="an2" attributeName="opacity" to="1" dur="0.001s" begin="an1.end+0.125s" fill="freeze" /> 
         <animate id="Back2" attributeName="opacity" to="0" dur="0.001s" begin="Back3.end+0.125s" fill="freeze" />
  </path>     
    <path class="st1" d="M43.8 50.4L78.8 66.7 82 59.7 47 43.3 43.8 50.4Z" >
       <animate id="an3" attributeName="opacity" to="1" dur="0.001s" begin="an2.end+0.125s" fill="freeze" />
         <animate id="Back3" attributeName="opacity" to="0" dur="0.001s" begin="Back4.end+0.125s" fill="freeze" />
  </path>   
    
  <path class="st1"  d="M53.5 33.2L83.2 57.9 88.1 52 58.4 27.3 53.5 33.2Z" >
      <animate id="an4" attributeName="opacity" to="1" dur="0.001s" begin="an3.end+0.125s" fill="freeze" />
        <animate id="Back4" attributeName="opacity" to="0" dur="0.001s" begin="Back5.end+0.125s" fill="freeze" />
  </path>
  
  <path class="st1"  d="M72.7 14.9L66.5 19.5 89.5 50.5 95.7 45.9 72.7 14.9Z" >
     <animate id="an5" attributeName="opacity" dur="0.001s" to="1" begin="an4.end+0.125s" fill="freeze" /> 
       <animate id="Back5" attributeName="opacity" dur="0.001s" to="0"  begin="an5.end+1s" fill="freeze" />
  </path>      
  
   <text x="30" y="115" font-size="14px" fill="#BCBBBB" >Click me</text>  
</svg>

Animation of recycle icons

  1. Contour drawing is based on changing stroke-dasharray parameters

  2. Contour filling from background color to basket color icons

<path class="st0"  d="M84.4 93.8V70.6h7.7v30.9H22.6V70.6h7.7v23.2z" stroke-dasharray="0,123.5 0,123.5" stroke-dashoffset="150"> 
        <!-- Cart outline drawing animation -->
     <animate id="bask" attributename="stroke-dasharray" dur="4s" begin="svg1.click" values="0,123.5 0,123.5;0,0,247,0" fill="freeze" />  
         <!--  Filling  baskets of the icon  color -->
       <animate id="bask_fill"  attributename="fill" dur="1s" begin="bask.end" values="white;#BCBBBB" fill="freeze" />
  </path>   

Below is the full code for the stackoverflow icon

<svg id="svg1" xmlns="http://www.w3.org/2000/svg" width="240" height="240" viewBox="0 0 120 120" style="border:1px solid;">
  <style>
    .st0{fill:white; stroke:#BCBBBB; stroke-width:2;}
    .st1{fill:#f48023;opacity:0;}

  </style>
  <path class="st0"  d="M84.4 93.8V70.6h7.7v30.9H22.6V70.6h7.7v23.2z" stroke-dasharray="0,123.5 0,123.5" stroke-dashoffset="150"> 
        <!-- Cart outline drawing animation -->
     <animate id="bask" attributename="stroke-dasharray" dur="4s" begin="svg1.click" values="0,123.5 0,123.5;0,0,247,0" fill="freeze" restart="never" />  
         <!--  Filling  baskets of the icon color -->
       <animate id="bask_fill"  attributename="fill" dur="1s" begin="bask.end" values="white;#BCBBBB" fill="freeze" restart="whenNotActive" />
  </path>   
   
  
    <path class="st1"  d="M38 86H76.6V78.3H38V86Z"> 
         <!--  Animation of the appearance of the first color strip -->
           <!--  Looping appearance, fading bands `begin="bask_fill.end;Back5.end+1.5s` -->
       <animate id="an1" attributeName="opacity" to="1" dur="0.001s" begin="bask_fill.end;Back5.end+1.5s" fill="freeze" restart="whenNotActive" /> 
            <!--  Animation of the disappearance of the first color strip -->
         <animate id="Back1" attributeName="opacity" to="0" dur="0.001s" begin="Back2.end+0.125s" fill="freeze" restart="whenNotActive" />
    </path>   
  <path class="st1" d="M38.8 68.4L76.6 76.3 78.2 68.7 40.4 60.8 38.8 68.4Z" >
         <!--  Animation of the appearance of the second colored strip -->
       <animate id="an2" attributeName="opacity" to="1" dur="0.001s" begin="an1.end+0.125s"
           fill="freeze" restart="whenNotActive" />     <!--  Animation of the disappearance of the second colored strip -->
         <animate id="Back2" attributeName="opacity" to="0" dur="0.001s"
             begin="Back3.end+0.125s"  fill="freeze" restart="whenNotActive" />
  </path>     
    <path class="st1" d="M43.8 50.4L78.8 66.7 82 59.7 47 43.3 43.8 50.4Z" >
       <animate id="an3" attributeName="opacity" to="1" dur="0.001s" begin="an2.end+0.125s"
           fill="freeze" restart="whenNotActive" />
         <animate id="Back3" attributeName="opacity" to="0" dur="0.001s"
             begin="Back4.end+0.125s" fill="freeze" restart="whenNotActive" />
  </path>   
    
  <path class="st1"  d="M53.5 33.2L83.2 57.9 88.1 52 58.4 27.3 53.5 33.2Z" >
      <animate id="an4" attributeName="opacity" to="1" dur="0.001s" begin="an3.end+0.125s" fill="freeze" />
        <animate id="Back4" attributeName="opacity" to="0" dur="0.001s" begin="Back5.end+0.125s" fill="freeze" />
  </path>
  
  <path class="st1"  d="M72.7 14.9L66.5 19.5 89.5 50.5 95.7 45.9 72.7 14.9Z" >
     <animate id="an5" attributeName="opacity" dur="0.001s" to="1" begin="an4.end+0.125s" fill="freeze" /> 
       <animate id="Back5" attributeName="opacity" dur="0.001s" to="0"  begin="an5.end+1s" fill="freeze" />
  </path> 
    <text x="30" y="115" font-size="14px" fill="#BCBBBB" >Click me</text>  
</svg>

Other color scheme

.container {
     width:30vw;
     height:30vh;
     }
    .st0{
    fill:#005999;
    stroke:white;
    stroke-width:2;}
    .st1 {
    fill:white;
    opacity:0;
    }
<div class="container">
<svg id="svg1" xmlns="http://www.w3.org/2000/svg"  viewBox="0 0 120 120" style="border:1px solid;">
  
    
    <rect width="100%" height="100%" fill="#005999" />
  <path class="st0"  d="M84.4 93.8V70.6h7.7v30.9H22.6V70.6h7.7v23.2z" 
        stroke-dasharray="0,123.5 0,123.5"   stroke-dashoffset="150"> 
        
     <animate id="bask" attributename="stroke-dasharray" dur="4s" begin="svg1.click" values="0,123.5 0,123.5;0,0,247,0" fill="freeze" restart="never" />  
         
       <animate id="bask_fill"  attributename="fill" dur="1s" begin="bask.end"
           values="#005999;white" fill="freeze" restart="whenNotActive" />
  </path>   
    
    <path class="st1"  d="M38 86H76.6V78.3H38V86Z"> 
         
       <animate id="an1" attributeName="opacity" to="1" dur="0.001s"
           begin="bask_fill.end;Back5.end+1.5s" fill="freeze" restart="whenNotActive" /> 
            
         <animate id="Back1" attributeName="opacity" to="0" dur="0.001s"
             begin="Back2.end+0.125s" fill="freeze" restart="whenNotActive" />
    </path>   
  <path class="st1" d="M38.8 68.4L76.6 76.3 78.2 68.7 40.4 60.8 38.8 68.4Z" >
         
       <animate id="an2" attributeName="opacity" to="1" dur="0.001s" 
         begin="an1.end+0.125s" fill="freeze" restart="whenNotActive" />    
         <animate id="Back2" attributeName="opacity" to="0" dur="0.001s" begin="Back3.end+0.125s" fill="freeze" restart="whenNotActive" />
  </path>     
    <path class="st1" d="M43.8 50.4L78.8 66.7 82 59.7 47 43.3 43.8 50.4Z" >
       <animate id="an3" attributeName="opacity" to="1" dur="0.001s" begin="an2.end+0.125s" fill="freeze" />
         <animate id="Back3" attributeName="opacity" to="0" dur="0.001s" begin="Back4.end+0.125s" fill="freeze" restart="whenNotActive" />
  </path>   
    
  <path class="st1"  d="M53.5 33.2L83.2 57.9 88.1 52 58.4 27.3 53.5 33.2Z" >
      <animate id="an4" attributeName="opacity" to="1" dur="0.001s" begin="an3.end+0.125s" fill="freeze" />
        <animate id="Back4" attributeName="opacity" to="0" dur="0.001s" begin="Back5.end+0.125s" fill="freeze" restart="whenNotActive" />
  </path>
  
  <path class="st1"  d="M72.7 14.9L66.5 19.5 89.5 50.5 95.7 45.9 72.7 14.9Z" >
     <animate id="an5" attributeName="opacity" dur="0.001s" to="1"
     begin="an4.end+0.125s" fill="freeze" restart="whenNotActive"/> 
       <animate id="Back5" attributeName="opacity" dur="0.001s" to="0" 
           begin="an5.end+1s" fill="freeze" restart="whenNotActive" />
  </path>   
      <text x="38" y="115" font-size="10px" fill="white" >Click me</text>  
</svg>
</div>

Upvotes: 7

Stranger in the Q
Stranger in the Q

Reputation: 3898

let s = c.width, // icon size
  w = s / 2.3, // block width
  h = s / 13, // block height
  start = Date.now(), // start time stamp
  fall = 900, // fall duration
  spring=200, // spring duration
  jump = 2000, // jump duration
  jumpDelay = 2700, // jump delay
  delay = i => i * (600 - i * 50), // block delay func
  clamp = (v, t) => Math.min(1, Math.max(0, v) / t), // clamp to 0-1 interval
  ctx = c.getContext("2d");

function draw() {
  let time = Date.now() - start; // frame timestamp 
  ctx.clearRect(0, 0, s, s); // clear
  ctx.fillStyle = "white"; // fill color

  // blocks
  [0, 1, 2, 3, 4].forEach(block => {

    // fall
    let t = clamp(time - delay(block), fall); // fall time
    let y = s * (t * t * t * 1.5 - 1.65 - .1 * block); // fall easing y = t^3

    // spring effect
    for (let i = 0; i < 5; i++) { // 5 times
      t = clamp(time - fall - delay(i), spring) - .6; // spring time
      y += (1 - t * t) * s * .09; // easing y = 1 - t^2
    }

    // jump
    t = clamp(time - jumpDelay, jump); // jump time
    // funny easing func "elastic"
    t = Math.pow(2, -10 * t) * Math.sin((t - .4 / 4) * (2 * Math.PI) / .4) + 1;
    let r = t * block * .075 * Math.PI; // block angle
    let x = s * .6 - Math.cos(r) * s * .6; // block x
    y -= Math.sin(r) * s * .6 - s * .1 * block * t; // block y

    // draw blocks
    ctx.save();
    ctx.translate(s / 2 + x, s / 2 + y);
    ctx.rotate(r);
    ctx.fillRect(-w / 2, -h / 2, w, h);
    ctx.restore();
  });

  // bin
  let y = s * 0.14;
  [
    [-w / 2 - h * 2, y, h, s * 0.25],
    [w / 2 + h, y, h, s * 0.25],
    [-w / 2 - h * 2, y + s * 0.2, w + h * 4, h]
  ]
  .forEach(r => ctx.fillRect(s / 2 + r[0], s / 2 + r[1], r[2], r[3]));

  requestAnimationFrame(draw);
}

addEventListener('click', () => start = Date.now());
draw();
<canvas id=c width=175 height=175 style='background:steelblue'><canvas>

Upvotes: 2

Related Questions