未能通过动画其“顶部”属性来动画 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>
<animate>
是如何工作的? ——保罗·勒博
mdn 文档相当完整::
SVG animation with SMIL<animate>
不要犹豫,查看其他信息页面的链接
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 这只是几行代码,不是很复杂......我可以添加解释,但是什么? 例如:这些是如何工作的?<animate>
是做什么的?为什么动画viewBox
有效?你是如何得出这些动画value
s 的? javascript的每一行是做什么的?等等。你也有一个非常不寻常的 JS 缩进样式。以更常规的方式重新格式化可能有助于理解代码。以上是关于未能通过动画其“顶部”属性来动画 SVG 中的 g 元素的主要内容,如果未能解决你的问题,请参考以下文章