使用 animate 标签为转换(旋转)的 SVG 组设置动画

Posted

技术标签:

【中文标题】使用 animate 标签为转换(旋转)的 SVG 组设置动画【英文标题】:Animate a transformed (rotated) SVG group with animate tag 【发布时间】:2021-06-07 11:29:34 【问题描述】:

我想要为已转换(旋转)的 SVG 组制作动画。为此,我插入了动画标签。在我的示例中,我正在为垂直线元素设置动画,因此动画标签插入到结束线标签之前。如果线没有被旋转,这将非常有效。但是,旋转线后,整个上下文都旋转了,我的动画指令也旋转了。我希望线条从顶部开始动画,向下到画布的中间,然后回到顶部。然而,在旋转之后,它从右侧进来并从右侧出去,因为整个上下文已被旋转(我的示例代码如下)。我尝试在结束组元素之前插入 animate 标记,并且还尝试了 animateTransform 标记。结束组标记之前的动画标记没有做任何事情,并且 animateTransform 标记给了我运动,但是线又是水平的,在错误的位置,并且它不尊重我的 keySplines 值(缓动)。我需要一些方法来保持我的元素转换,但能够根据用户的说明从上/右/下/左动画进/出。

我需要一个内联的 SVG 解决方案(而不是 CSS)。该应用程序是一个视频幻灯片编辑器,可导出此代码块,该代码块在以 html/SVG 编写的播放器上呈现。我的幻灯片编辑器使用 Fabric JS 编辑和导出 SVG 元素。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 992 558" xml:space="preserve" preserveAspectRatio="none" style="position:absolute; width:100%; left:0; background-color: null" id="svg">
  <desc>Created with Fabric.js 3.6.3</desc>
  <defs></defs>
  <g transform="matrix(0 0.68 -1 0 455.92 235.39)">
    <line style="stroke: rgb(0,0,0); stroke-width: 4; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x1="-175" y1="0" x2="175" y2="0" layerId="1">
      <animate attributeName="y1" attributeType="XML" begin="0.7441050156739812s" dur="1.25s" values="-1000; 0" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.14 0.22 0.12 0.99" />
      <set attributeName="visibility" from="hidden" to="visible" begin="0.7441050156739812s" />
      <animate attributeName="y2" attributeType="XML" begin="0.7441050156739812s" dur="1.25s" values="-1000; 0" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.14 0.22 0.12 0.99" />
      <set attributeName="visibility" from="hidden" to="visible" begin="0.7441050156739812s" />
      <animate attributeName="y1" attributeType="XML" begin="2.132496081504702s" dur="1.25s" values="0; -1000" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.7 0 0.53 0.99" />
      <set attributeName="visibility" from="visible" to="hidden" begin="4.132496081504701s" />
      <animate attributeName="y2" attributeType="XML" begin="2.132496081504702s" dur="1.25s" values="0; -1000" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.7 0 0.53 0.99" />
      <set attributeName="visibility" from="visible" to="hidden" begin="4.132496081504701s" />
    </line>
  </g>
</svg>

【问题讨论】:

您的用例是否可以通过更改 xy 属性来以这种方式旋转线条,或者该组内是否有更多(和不同)元素? 如果运行代码sn -p,可以看到线是垂直的。这就是意图。我想要它做的是保持垂直,但从顶部滑入,然后从画布上滑回顶部。现在它从右边滑入/滑出,因为包括动画标签在内的整个组都已被转换。 【参考方案1】:

我很确定我上面的评论被误解了,所以我使用我想到的技术提供了一个基本的答案。

不是旋转整个组,而是做一条垂直线,而是摆脱组上的旋转,而是以这种方式设置x1x2y1y2坐标,你得到一条垂直线。这样您就可以轻松地应用动画,而无需旋转任何东西。基本思想概述如下:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 992 558" xml:space="preserve" preserveAspectRatio="none" style="position:absolute; width:100%; left:0; background-color: null" id="svg">
  <desc>Created with Fabric.js 3.6.3</desc>
  <defs></defs>
  <g>
    <line style="stroke: rgb(0,0,0); stroke-width: 4; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x1="10" y1="-175" x2="10" y2="175" layerId="1">
      <animate attributeName="y1" attributeType="XML" begin="0.7441050156739812s" dur="1.25s" values="0; 500" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.14 0.22 0.12 0.99" />
      <set attributeName="visibility" from="hidden" to="visible" begin="0.7441050156739812s" />
      <animate attributeName="y2" attributeType="XML" begin="0.7441050156739812s" dur="1.25s" values="-350; 150" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.14 0.22 0.12 0.99" />
      <set attributeName="visibility" from="hidden" to="visible" begin="0.7441050156739812s" />
    </line>
  </g>
</svg>

但是,您也可以在为属性设置动画时仅考虑旋转(因此,然后为 x1x2 属性设置动画,而不是 y1y2):

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 992 558" xml:space="preserve" preserveAspectRatio="none" style="position:absolute; width:100%; left:0; background-color: null" id="svg">
  <desc>Created with Fabric.js 3.6.3</desc>
  <defs></defs>
  <g transform="matrix(0 0.68 -1 0 455.92 235.39)">
    <line style="stroke: rgb(0,0,0); stroke-width: 4; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke" x1="-175" y1="0" x2="175" y2="0" layerId="1">
      <animate attributeName="x1" attributeType="XML" begin="0.7441050156739812s" dur="1.25s" values="-1000; 0" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.14 0.22 0.12 0.99" />
      <set attributeName="visibility" from="hidden" to="visible" begin="0.7441050156739812s" />
      <animate attributeName="x2" attributeType="XML" begin="0.7441050156739812s" dur="1.25s" values="-650; 350" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.14 0.22 0.12 0.99" />
      <set attributeName="visibility" from="hidden" to="visible" begin="0.7441050156739812s" />
      <animate attributeName="x1" attributeType="XML" begin="2.132496081504702s" dur="1.25s" values="0; -1000" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.7 0 0.53 0.99" />
      <set attributeName="visibility" from="visible" to="hidden" begin="4.132496081504701s" />
      <animate attributeName="x2" attributeType="XML" begin="2.132496081504702s" dur="1.25s" values="350; -650" repeatCount="1" fill="freeze" calcMode="spline" keySplines="0.7 0 0.53 0.99" />
      <set attributeName="visibility" from="visible" to="hidden" begin="4.132496081504701s" />
    </line>
  </g>
</svg>

还请记住,x1x2 必须保持相同的距离(在您发布的代码中是 350)。

【讨论】:

以上是关于使用 animate 标签为转换(旋转)的 SVG 组设置动画的主要内容,如果未能解决你的问题,请参考以下文章

利用velocity.js将svg动起来

Adobe Animate Snap SVG 插件 - 巨大的文件

使用 <path> 标签将图标图像转换为 svg 的最佳方法

将 svg 标签转换为图像中的嵌入 svg

SVG 到 CDR 转换器

如何在SVG中旋转期间保持文本方向不变