如何对 svg 内的(路径)元素进行动画处理以放大或缩小,而无需视觉上移动位置

发布于 2025-01-16 01:18:39 字数 2937 浏览 0 评论 0原文

我有一个 svg,其中包含一些如下所示的元素:

svg contains 3 个圆圈和 2 个路径

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

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

我尝试探索属性转换原点的不同值,但似乎没有一个能够实现所需的行为。

我已经包含了一个显示行为的演示代表:

#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>

I have an svg with a few elements that looks something like this:

svg containing 3 circles and 2 paths

I would like to create an animation where each element "pulses" (grows about 20% in size and then returns to its normal size without moving to a different position) one after the other, going around in a circle on repeat.

I began creating a css animation for this but my attempts to add a scale animation clearly were not using the correct center point because every scaling movement would shift that element to a different position as well.

I tried exploring different values for the property transform-origin, but none seemed to achieve the desired behaviour.

I have included a demo reprex that shows the behaviour:

#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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

久夏青 2025-01-23 01:18:39

当您使用 CSS“覆盖”transform 时,translate 将被删除。在这里,我将变换/翻译移至父级 。因此,使用 中的变换来移动每个元素,然后使用 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>

When you "overwrite" the transform using CSS the translate is removed. Here I moved the transform/translate to a parent <g>. So each element is moved using the transform in <g> and then each element is scaled using CSS.

The circles are easy to scale because their origin is in the center already, but the other shapes need either to be moved so that 0,0 is in the center (change all values in the d attribute) or use transform-origin to move the origin. I guess that the result here is a combination - that could be optimized (up to you :-)).

#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>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文