未能通过动画其“顶部”属性来动画 SVG 中的 g 元素

Posted

技术标签:

【中文标题】未能通过动画其“顶部”属性来动画 SVG 中的 g 元素【英文标题】:Failure to animate a g element in SVG by animating its "top" property 【发布时间】:2021-09-09 20:39:38 【问题描述】:

所以,如果你检查一下小提琴,(https://jsfiddle.net/xXnikosXx/6jx2rpsf/3/) 我有一个 SVG 图像,有几个对象和一个蒙版。它掩盖了隐藏在其下方的文本(彩色线条),并计划对其顶部位置进行动画处理,使下方的文本出现,顶部的文本消失,以产生文本滚动效果。没有蒙版的文本如下图所示,以防万一。 here 我以为动画发生时文本会出现,但事实并非如此(如果您移除蒙版,文本会正确显示和动画,但它们的图层错误,因此文本显示在其他所有内容之上)

我想不出一种使用蒙版使文本正确动画的方法,是否可以使用某些东西代替蒙版来获得相同的结果,但没有文本问题?

相关代码:

<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="354" y="174"  >
  <rect id="laptop-screen-front" x="354" y="174"   fill="white" />
</mask>
<g mask="url(#mask0)">

<!-- some of the lines that represent text: -->
<g id="text-lines">
  <line id="Line 3" x1="408" y1="194.5" x2="433" y2="194.5" stroke="#E06C60" stroke- />
  <line id="Line 23" x1="438" y1="194.5" x2="463" y2="194.5" stroke="#D18C4C" stroke- />
  <line id="Line 35" x1="469" y1="194.5" x2="542" y2="194.5" stroke="#7BC379" stroke- />
  <line id="Line 36" x1="469" y1="209.5" x2="525" y2="209.5" stroke="#7BC379" stroke- />
</g>

【问题讨论】:

我不确定我看到小提琴出了什么问题,并且问题中的示例代码本身并没有为面具设置动画。 【参考方案1】:

您的代码不会为蒙版设置动画。它尝试为 text-lines g 元素的位置设置动画。但是 SVG 不是 html。它是它自己的东西,不支持许多常见的 CSS 属性:例如与您最相关 - SVG 中没有“顶部”属性。做你想做的最简单的方法是去掉所有的 CSS 动画,并将一个变换和一个 SMIL 动画直接添加到 SVG 的以下部分。

 <g mask="url(#mask0)">
    <g id="text-lines" transform="translate(0 0)">
    <animateTransform attributeName="transform" type="translate" values="0 0; 0 -150; 0 0" dur="11s" repeatCount="indefinite"/>
    <line id="Line 3" x1="408" .... etc.

顺便说一句 - 对动画使用变换的原因之一是浏览器通常可以通过在 GPU 上制作动画来优化事物 - 所以它比 viewBox 或***动画更好。

【讨论】:

【参考方案2】:

2 种方法:

    使用 SMIL

svg#parent 
  background-color: rgba(100, 148, 237, 0.3);
<svg id="parent"   viewBox="0 0 200 100">
  <rect x="10" y="10"   fill="white"  />
  <svg  x="10" y="10"   viewBox="0 0 180 20" >
    <text x="20" y="15" > hello </text>
    <text x="20" y="35" > world </text>
    <animate attributeName="viewBox" 
       values="0 0 180 20; 0 20 180 20; 0 0 180 20" 
       begin="1s" dur="2s" repeatCount="indefinite" />
  </svg>
</svg>
    使用 javascript - requestAnimationFrame

(function()
  
  const
    svgInside = document.querySelector('#insideSVG')
  , moving    = .7 // change the value to slow down or speed up
    ;
  let 
    stepVal = moving
  , stepPos = 0
    ;
  requestAnimationFrame(step)
    ;
  function step()
    
    stepPos += stepVal

    if (stepPos<=0)  stepVal = moving
    if (stepPos>=20) stepVal = -moving

    svgInside.setAttribute('viewBox',`0 $stepPos 180 20`)
  
    requestAnimationFrame(step)
    
  
)()
svg#parent 
  background-color: rgba(100, 148, 237, 0.3);
<svg id="parent"   viewBox="0 0 200 100">
  <rect x="10" y="10"   fill="white" />
  <svg  x="10" y="10"   viewBox="0 0 180 20"
        id="insideSVG" >
    <text x="20" y="15" > hello </text>
    <text x="20" y="35" > world </text>
  </svg>
</svg>

对于您的 SVG,值应该是:


<svg  x="354" y="174"   viewBox="354 174 733 344" >
   <line x1="419" y1="187.5" ..... />

/.../

   <animate attributeName="viewBox" 
     values="354 174 733 344; 354 520 733 344; 354 174 733 344" 
      begin="1s" dur="8s" repeatCount="indefinite" />
</svg>

&lt;animate&gt; 是如何工作的? ——保罗·勒博

mdn 文档相当完整::

SVG animation with SMIL &lt;animate&gt;

不要犹豫,查看其他信息页面的链接

but if you want a general vision of the animation possibilities of your SVGs, the Wikipedia page is ideal

甚至有一部分显示了requestAnimationFrame()的使用,我在这里使用。

PS:Whitesmith 风格自 1978 年以来就已经存在,不,我不是出于审美原因使用它,而是因为它检查正确的大括号对是否构成正确的代码片段。出于同样的原因,我将逗号放在数据行的前面(它们在行尾是不可见的[并且经常被遗忘]),以及列对齐方式(两者都在 Haskell 中使用类似的方式)不,K&R 不是万无一失的风格,也不比任何其他风格更合法。

【讨论】:

这个答案可以通过一些解释来改进 @Sean 这只是几行代码,不是很复杂......我可以添加解释,但是什么? 例如:这些是如何工作的? &lt;animate&gt; 是做什么的?为什么动画viewBox 有效?你是如何得出这些动画values 的? javascript的每一行是做什么的?等等。你也有一个非常不寻常的 JS 缩进样式。以更常规的方式重新格式化可能有助于理解代码。

以上是关于未能通过动画其“顶部”属性来动画 SVG 中的 g 元素的主要内容,如果未能解决你的问题,请参考以下文章

如何为 svg 动画提供更多空间?

CSS 过渡属性覆盖 SVG 元素上的 jQuery 动画时间

SVG 动画:Chrome 中的迟缓/性能不佳

svg动画类库Snap.svg简介

玩转SVG线条动画

SVG 签名动画 制作