【问题标题】:Anime.js SVG Morph Animation Breaks Shape PathAnime.js SVG 变形动画打破形状路径
【发布时间】:2020-05-16 08:25:49
【问题描述】:

我正在尝试使用 Anime.js 将圆形的 SVG(使用 Object > Compound Path > Make 转换为 Illustrator 中的路径)变成正方形(以相同的方式转换),但是当时间轴运行时,圆圈形状被扭曲,好像路径没有被正确解释。

虽然方形看起来不错。

作为测试,您可以将shape的目标类从标记中的SVG中删除,以防止Anime.js运行并且圆圈将正确显示。

为什么 Anime.js 无法读取我的圈子?

const circlePath = 'M153.1,49.5c63.2,0,114.5,51.3,114.5,114.5s-51.3,114.5-114.5,114.5S38.6,227.2,38.6,164S89.9,49.5,153.1,49.5z';
const squarePath = 'M270.7,275.7H23.9V31h246.8V275.7z';

var timeline = anime.timeline({
  autoplay: true,
  direction: "alternate",
  loop: true
});

timeline.add({
  targets: ".shape",
  d: {
    value: [
      circlePath,
      squarePath
    ],
    duration: 1500,
    easing: "easeInOutQuad"
  },
  offset: 1500
});
svg {
  margin: 1rem;
  border: 2px solid #666;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
<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="300px" height="300px" viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
  <path class="shape" fill="blue" d="M153.1,49.5c63.2,0,114.5,51.3,114.5,114.5s-51.3,114.5-114.5,114.5S38.6,227.2,38.6,164S89.9,49.5,153.1,49.5z"/>
</svg>

【问题讨论】:

    标签: javascript svg svg-animate anime.js


    【解决方案1】:

    要从一种形状平滑变形到另一种形状,必须满足几个条件

    • 初始图中和最终图中的节点数 必须相同
    • 路径起点的相同节点应具有 相同的形状。 (贝塞尔曲线的 C、Q、T、S)

    您可以使用任何矢量编辑器获得满足这些要求的路径。
    假设您想实现将圆形平滑变形为矩形

    在矢量编辑器中画一个圆圈

    沿对角线再添加四个点,将需要它们来将圆的轮廓变为正方形

    以* .svg 格式保存文件并将path 复制到另一个文件。这将是变形的初始图形。 接下来,将这四个锚点拖到正方形的角上,并调整锚点的控制点(图中蓝色箭头)

    在矢量编辑器中再次保存文件并复制第二个path这将是最终的变形图

    path 替换为应用程序中的初始元素和最终元素:

    const circlePath = 'm268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z';
    const squarePath = 'm268.3 164.3c0 31.4 0 86.7 0 115.1-26.6 0-82.9 0-115.1 0-31.5 0-73.4 0-114.2 0-0.9-26.3-0.9-83.1-0.9-115.1 0-31.1 0-87 0-115.1 26 0 82.6 0 115.1 0 32.3 0 91.9 0 115.1 0.9 0 30.9 0 83 0 114.2z';
    
    var timeline = anime.timeline({
      autoplay: true,
      direction: "alternate",
      loop: true
    });
    
    timeline.add({
      targets: ".shape",
      d: {
        value: [
          circlePath,
          squarePath
        ],
        duration: 1500,
        easing: "easeInOutQuad"
      },
      offset: 500
    });
    svg {
      margin: 1rem;
      border: 2px solid #666;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
    <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="300px" height="300px" viewBox="0 0 300 300" style="enable-background:new 0 0 300 300;" xml:space="preserve">
      <path class="shape" fill="blue" d="m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z"/>
    </svg>

    最困难的事情是得到正确的path 公式。拥有它们,您可以在不使用纯 SVG 的 Javascript 的情况下实现变形

    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink"
    	  
         width="300" height="300" viewBox="0 0 300 300" >  
     <style>
      path {
      fill:dodgerblue;
      stroke:none;
      }
     </style>
     
    <path  d="m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z" stroke="black" fill="dodgerblue">
       <animate attributeName="d"
         begin="0s"
    	 dur="3s"
    	 values="
    	         m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z;
    			 
    			 m268.3 164.3c0 31.4 0 86.7 0 115.1-26.6 0-82.9 0-115.1 0-31.5 0-73.4 0-114.2 0-0.9-26.3-0.9-83.1-0.9-115.1 0-31.1 0-87 0-115.1 26 0 82.6 0 115.1 0 32.3 0 91.9 0 115.1 0.9 0 30.9 0 83 0 114.2z"
    			 repeatCount="indefinite"
    			 fill="freeze"
    	/>		 
     </path> 
    </svg>	
    
     

    反向运动

    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
        xmlns:xlink="http://www.w3.org/1999/xlink"
    	  
         width="300" height="300" viewBox="0 0 300 300" >  
     <style>
      path {
      fill:dodgerblue;
        }
     </style>
     
    <path  d="m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z">
       <animate attributeName="d"
         begin="0s"
    	 dur="5s"
    	 values="
    	         m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z;
    			 
    			 m268.3 164.3c0 31.4 0 86.7 0 115.1-26.6 0-82.9 0-115.1 0-31.5 0-73.4 0-114.2 0-0.9-26.3-0.9-83.1-0.9-115.1 0-31.1 0-87 0-115.1 26 0 82.6 0 115.1 0 32.3 0 91.9 0 115.1 0.9 0 30.9 0 83 0 114.2z;
    			 
    			 m268.3 164.3c0 31.4-12.6 59.9-33 80.7-20.9 21.2-49.9 34.4-82 34.4-31.5 0-60.1-12.7-80.9-33.3-21.1-20.9-34.1-49.8-34.1-81.8 0-31.1 12.3-59.3 32.4-80 20.9-21.6 50.2-35.1 82.7-35.1 32.3 0 61.6 13.3 82.5 34.8 20.2 20.7 32.6 49 32.6 80.2z;"
    			 
    			 repeatCount="indefinite"
    			 fill="freeze" 	/>		 
    			 
     </path> 
    
    </svg>

    平滑的变形动画也可以用SnapJS

    var svg = document.getElementById("svg1");
    var s = Snap(svg);
    
    var simpleCup = Snap.select('#coffee-cup');
    var fancyCup = Snap.select('#fancy-cup');
    
    var simpleCupPoints = simpleCup.node.getAttribute('d');
    var fancyCupPoints = fancyCup.node.getAttribute('d');
    
    
    var toFancy = function(){
      simpleCup.animate({ d: fancyCupPoints }, 1000, mina.backout, toSimple);  
    }
    
    var toSimple = function(){
      simpleCup.animate({ d: simpleCupPoints }, 1000, mina.backout, toFancy); 
    }
    
    
    toSimple();
     <svg id="svg1" width="100" height="130" viewBox="0 0 75 47" xmlns="http://www.w3.org/2000/svg">
    	<path id="coffee-cup" fill="#5F0C2D" stroke="#5F0C2D"  d="M0.4 5.9C0.4 6.3-0.3 17.8 4.3 31.2 5.3 32.4 6.1 37.9 7.5 43 10.4 53.6 10 58.2 10 58.2 10 58.2 10 59.1 10 62.2L10 63.4 15 65.7C20.1 67.8 34 67.6 38.6 65.7L44 64 44 62.2C44 60.3 44 61.2 44 59.6 44 59.6 44 58.2 44 58.2 44 58.2 44 56 44 56 44 56.1 44.2 52.2 44.2 52.2 44.2 52.2 44.5 49.3 44.5 49.3 44 47 46.8 39.1 47.6 38.8 48.4 38.6 52.8 37.6 55.4 37 62.3 36.7 68.5 30.5 68.5 26.9 68.5 25.1 68.5 20.3 66.1 17.8 63.5 14.8 60.4 14.1 56.7 14.2 54.2 14.3 54.2 12.8 54 12.6 53.8 12.5 54 12.6 54 10.8L53.3 6.7 51.3 4.6C49.8 3.6 47.5 3 44.7 2.2 38.3 0.5 20.1 0 12.7 1.4 7 2.4 0.4 4.7 0.4 5.9ZM64.8 22.9C64.8 25.9 65.5 27.9 60.6 31.8 59.6 32.6 64 30.3 62.9 30.8 60.9 31.9 53.6 32.7 52.4 31.8 51.6 31.1 51.1 29.8 51 28 51.3 24.6 52.1 22.1 53.6 20.4 57.4 16 64.8 19.2 64.8 22.9Z"  />
        <path opacity="0"  id="fancy-cup" fill="#5F0C2D" stroke="#5F0C2D"  d="M0 6.8C0 7.2 0.9 8.5 1.9 9.6 2.9 10.8 4.9 15.9 6.3 21 9.2 31.6 12.4 36.5 17.5 38.2 21.6 39.6 21.7 39.8 18.8 42.2L16.5 44 19.5 45.3C24.6 47.4 37 47.6 41.6 45.7L45.5 44.1 43.1 42.1C41 40.4 40.9 39.9 42.1 39.1 42.8 38.6 44.2 38.2 45.1 38.2 47 38.2 52.4 33.5 53.2 31.2 53.6 29.9 53.9 29.9 55.3 31 57.5 32.9 59.1 31.6 58.4 28.6 58 27 58.3 26.1 59.1 25.8 59.9 25.6 62.6 24.8 65.2 24.2 70.7 22.7 75 19 75 15.5 75 13.7 74.1 12.7 71.3 11.6 68 10.2 67.3 10.2 63.7 11.6 61.4 12.5 59.5 13 59.3 12.8 59.1 12.7 59.9 11.3 61 9.9L63.1 7.3 60.5 5.6C59 4.6 55.5 3.2 52.7 2.4 46.3 0.7 21.5-0.1 14.1 1.3 8.4 2.3 0 5.6 0 6.8ZM70 15.6C70 18.6 65.7 22.2 62.3 22.2 61 22.2 59 22.7 57.9 23.2 55.9 24.3 55.5 23.6 56.6 20.8 56.9 19.9 57.6 19.5 58.1 19.8 58.6 20.1 60.5 18.7 62.2 16.8 66 12.4 70 11.9 70 15.6Z"  />
    
    </svg>
      
      <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>

    【讨论】:

    • @Chris 如果答案对您有用,请不要忘记将其标记为解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    • 2021-09-08
    • 1970-01-01
    相关资源
    最近更新 更多