如何为 svg 中的(路径)元素设置动画以在不视觉移动位置的情况下放大和缩小

How to animate a (path) element inside an svg to scale larger and smaller without moving position visually

我有一个带有一些元素的 svg,看起来像这样:

我想创建一个动画,其中每个元素“脉动”(大小增长约 20%,然后 returns 恢复到正常大小而不移动到不同的位置)一个接一个地循环在循环中重复。

我开始为此创建一个 css 动画,但我尝试添加缩放动画显然没有使用正确的中心点,因为每次缩放移动也会将该元素移动到不同的位置。

我尝试探索 属性 变换原点的不同值,但 none 似乎达到了预期的效果。

我已经包含了一个演示行为的演示 reprex:

#Ellipse_1 {
  /* No transform-origin */
  animation: pulse 2s linear infinite alternate;
  animation-delay: 2.6s fill-opacity: 50%;
}

#Ellipse_2 {
  /* transform-origin same as circle's center location */
  transform-origin: 4 8;
  fill-opacity: 50%;
  animation: pulse 2s linear infinite alternate;
  animation-delay: 3.4s
}

#Ellipse_3 {
  /* Trying transform-origin center center keyword */
  transform-origin: center center;
  fill-opacity: 50%;
  animation: pulse 2s linear infinite alternate;
  animation-delay: 3s
}

#Path_1 {
  /* Trying transform-origin center keyword */
  transform-origin: center;
  animation: pulse 2s linear infinite alternate;
  animation-delay: 4s
}

#Path_2 {
  /* This goes off screen as soon as animation starts */
  animation: pulse 2s linear infinite alternate;
  animation-delay: 4s
}

@keyframes pulse {
  0% {
    transform: scale(1);
    -ms-transform: scale(1);
    -webkit-transform: scale(1);
  }
  100% {
    transform: scale(2);
    -ms-transform: scale(2);
    -webkit-transform: scale(2);
  }
}
<svg id="shapes" data-name="shapes data" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-10 -10 100 100">
      <circle id="Ellipse_1" data-name="Ellipse 1" cx="2.083" cy="2.083" r="2.083" transform="translate(14 3)" fill="red"/>
      <path id="Path_1" data-name="Path 259" d="M60.749,74.282a103.267,103.267,0,0,0-5.686,23.5.459.459,0,0,1-.455.408H48.887a.46.46,0,0,1-.453-.38l-3.1-17.357a.458.458,0,0,1,.321-.519A75.754,75.754,0,0,0,60.24,73.846C60.708,73.591,60.936,73.783,60.749,74.282Z" transform="translate(-45.326 -63.944)" fill-rule="evenodd" fill="green"/>
      <circle id="Ellipse_2" data-name="Ellipse 2" cx="2.083" cy="2.083" r="2.083" transform="translate(4 8)" fill="blue"/>
      <circle id="Ellipse_3" data-name="Ellipse 3" cx="1.62" cy="1.62" r="1.62" transform="translate(21.942)" fill="green"/>
      <path id="Path_2" data-name="Path 2" d="M97.486,54.462C94.879,58.549,90.751,66.907,88.6,81.11a.6.6,0,0,1-.572.505,16.478,16.478,0,0,0-8.995,3.049.355.355,0,0,1-.562-.322,90.68,90.68,0,0,1,6.77-25.419.966.966,0,0,1,.352-.4q1.521-.866,3.1-1.629a.016.016,0,0,1,.009,0,50.611,50.611,0,0,1,8.261-3.124h0A.465.465,0,0,1,97.486,54.462Z" transform="translate(-66.545 -51.149)" fill-rule="evenodd" fill="red"/>
    </svg>

当您使用 CSS“覆盖”transform 时,translate 将被删除。在这里,我将 transform/translate 移到了父级 <g>。因此每个元素都使用 <g> 中的变换移动,然后使用 CSS.

缩放每个元素

圆圈很容易缩放,因为它们的原点已经位于中心,但其他形状需要移动以便 0,0 位于中心(更改 d 属性中的所有值)或使用 transform-origin移动原点。我想这里的结果是一个组合 - 可以优化(由你决定:-))。

#Ellipse_1 {
  /* No transform-origin */
  animation: pulse 2s linear infinite alternate;
  animation-delay: 2.6s fill-opacity: 50%;
}

#Ellipse_2 {
  /* transform-origin same as circle's center location */
  fill-opacity: 50%;
  animation: pulse 2s linear infinite alternate;
  animation-delay: 3.4s
}

#Ellipse_3 {
  /* Trying transform-origin center center keyword */
  fill-opacity: 50%;
  animation: pulse 2s linear infinite alternate;
  animation-delay: 3s
}

#Path_1 {
  /* Trying transform-origin center keyword */
  transform-origin: 50px 80px;
  animation: pulse 2s linear infinite alternate;
  animation-delay: 4s
}

#Path_2 {
  /* This goes off screen as soon as animation starts */
  transform-origin: 80px 70px;
  animation: pulse 2s linear infinite alternate;
  animation-delay: 4s
}

@keyframes pulse {
  0% {
    transform: scale(1);
    -ms-transform: scale(1);
    -webkit-transform: scale(1);
  }
  100% {
    transform: scale(1.2);
    -ms-transform: scale(1.2);
    -webkit-transform: scale(1.2);
  }
}
<svg id="shapes" data-name="shapes data" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <g transform="translate(14 3)">
    <circle id="Ellipse_1" data-name="Ellipse 1" cx="2.083" cy="2.083" r="2.083" fill="red"/>
  </g>
  <g transform="translate(-45.326 -63.944)">
    <path id="Path_1" data-name="Path 259" d="M60.749,74.282a103.267,103.267,0,0,0-5.686,23.5.459.459,0,0,1-.455.408H48.887a.46.46,0,0,1-.453-.38l-3.1-17.357a.458.458,0,0,1,.321-.519A75.754,75.754,0,0,0,60.24,73.846C60.708,73.591,60.936,73.783,60.749,74.282Z" fill-rule="evenodd" fill="green"/>
  </g>
  <g transform="translate(4 10)">
    <circle id="Ellipse_2" data-name="Ellipse 2" r="2.083"  fill="blue"/>
  </g>
  <g transform="translate(22 3)">
    <circle id="Ellipse_3" data-name="Ellipse 3" r="1.62"  fill="green"/>
  </g>
  <g transform="translate(-66.545 -51.149)">
    <path id="Path_2" data-name="Path 2" d="M97.486,54.462C94.879,58.549,90.751,66.907,88.6,81.11a.6.6,0,0,1-.572.505,16.478,16.478,0,0,0-8.995,3.049.355.355,0,0,1-.562-.322,90.68,90.68,0,0,1,6.77-25.419.966.966,0,0,1,.352-.4q1.521-.866,3.1-1.629a.016.016,0,0,1,.009,0,50.611,50.611,0,0,1,8.261-3.124h0A.465.465,0,0,1,97.486,54.462Z"  fill-rule="evenodd" fill="red"/>
  </g>
</svg>