Search code examples
cssanimationsvgsvg-animatesmil

Shape "8" looped animation with SVG <animate> only


I'm having massive headaches trying to fin the sweet-spot to achieve "8" shape animation using the combination of just <animate attributeName="cx"> and <attributeName="cy">.
I'll like to do it using that since it seems, by my metrics, that it's the most performant in terms of FPS, CPU and GPU usage.

Quick demo of the "ideal" motion path: https://codepen.io/ivancis/pen/eYmZowz


Solution

  • New solution caused by refinements in comments

    I need to animate a svg element using just a combination of <animate attributeName="cx"> <animate attributeName="cy"> (for performance) to make an "8" shape motion, looped

    Since the author does not want to use the animateMotion command, in this case   I see only one way to implement the animation of the movement of the circle along the infinity symbol:

    It is necessary to sequentially select many points along the infinity symbol and assign their coordinates to the circle cx = "x", cy = "y"

    The more points you select, the closer the trajectory moving of the circle along the infinity symbol

    enter image description here

    In the vector editor, I sequentially put circles on the infinity symbol and wrote down their coordinates of the center of the circle. The first circle has the center coordinates cx ="70" cy ="60"
    So, it was done for all circles located along the infinity symbol. The last circle has the same coordinates as the first one, thereby realizing a closed cycle

    It remains only to substitute these values in the animation formulas cx, cy

    Circle motion animation cx, cy with radius r="5

     <div class="group">
      
      <svg class="ball" xmlns="http://www.w3.org/2000/svg" width="50%" height="50%" viewBox="0 0 120 120">    
      
        
        <circle fill="olive" cx="70" cy="60" r="5">
          <animate
                  attributeName="cx"
                  attributeType="XML"
                  repeatCount="indefinite"
                  begin="0s"
                  dur="2s"
                  values="70;65;60;55;50;45;40.5;40.5;42.5;45.1;48.7;52;55;58;60;61;61;61;61;61;61;62.9;66;69;
    			  73;76;79;81;80;78;74;70">
                  
            </animate>
    		  <animate
    				  attributeName="cy"
    				  attributeType="XML"
    				  repeatCount="indefinite"
    				  begin="0"
    				  dur="2s"
    				  values="60;60;60;60;60;58.3;52.5;47.9;44.4;41.8;40.3;40;41;43;47;51;55;60;65;70;74;77;79;
    				  80;80;79;76;72;67;64;61;60">							 
    		  </animate>   
    	</circle>
    	  	    
    	   <path fill="none" stroke="black" stroke-dasharray="2" d="M70.5,60.5c5.5,0,10,4.5,10,10s-4.5,10-10,10s-10-4.5-10-10v-20c0-5.5-4.5-10-10-10s-10,4.5-10,10 s4.5,10,10,10H70.5z"/>
      </svg>
    </div>
      

    Radius r = 40 as in the example of the author of the question

     <div class="group">
      
      <svg class="ball" xmlns="http://www.w3.org/2000/svg" width="50%" height="50%" viewBox="0 0 120 120">    
      
        
        <circle fill="olive" cx="70" cy="60" r="40">
          <animate
                  attributeName="cx"
                  attributeType="XML"
                  repeatCount="indefinite"
                  begin="0s"
                  dur="2s"
                  values="70;65;60;55;50;45;40.5;40.5;42.5;45.1;48.7;52;55;58;60;61;61;61;61;61;61;62.9;66;69;
    			  73;76;79;81;80;78;74;70">
                  
            </animate>
    		  <animate
    				  attributeName="cy"
    				  attributeType="XML"
    				  repeatCount="indefinite"
    				  begin="0"
    				  dur="2s"
    				  values="60;60;60;60;60;58.3;52.5;47.9;44.4;41.8;40.3;40;41;43;47;51;55;60;65;70;74;77;79;
    				  80;80;79;76;72;67;64;61;60">							 
    		  </animate>   
    	</circle>
    	  	    
    	   <path fill="none" stroke="black" stroke-dasharray="2" d="M70.5,60.5c5.5,0,10,4.5,10,10s-4.5,10-10,10s-10-4.5-10-10v-20c0-5.5-4.5-10-10-10s-10,4.5-10,10 s4.5,10,10,10H70.5z"/>
      </svg>
    </div>