autorotate: [
first position property, like "x",
second position property, like "y",
rotation property, typically "rotation" but can be “rotationY”,
integer for radians/degrees the rotation starts from like 10,
boolean for radians or degrees- radians is true
]
SMIL,SVG 的原生动画规范,曾经风光无限,凭借着其强大的功能和高效的渲染能力,在 SVG 动画领域呼风唤雨。然而,时过境迁,SMIL 的支持在 WebKit 中日渐式微,而微软的 IE 和 Edge 浏览器更是从未支持过 SMIL,也几乎不可能在未来支持。
别担心!我们今天就来探讨一些 SMIL 特有的功能,并深入研究如何用其他方法来实现相同的效果,以确保你的动画能拥有更广泛的浏览器兼容性。
🏃🏻♀️ 沿着路径运动
SMIL 最吸引人的地方之一就是它能够让 SVG 对象沿着路径运动,从而实现更加逼真的动画效果。毕竟,现实生活中很少有物体是沿着直线运动的,沿着路径运动可以让我们模拟现实生活中的各种运动轨迹。
在过去,你需要将 SVG 路径数据传递给
animateMotion
元素,并使用path
属性来定义路径数据。然后,你可以通过xlink:href
属性来指定要进行动画的元素。替代方案:CSS
幸运的是,现在 CSS 也支持沿着路径运动的功能了!虽然目前支持的浏览器还不多(仅限于 Chrome、Opera 和 Android),但 Sara Soueidan 已经提议在 Edge 中加入该功能,并且得到了强烈的支持,在本文发布时已经获得了超过 420 票。请加入我们,一起呼吁该功能早日实现!Firefox 的投票页面 在这里。
至于 Safari,据我所知,它的支持情况可能需要单独处理。我已经注册了一个 bug 报告,并请求在 CSS 中添加沿着路径运动的功能。
为了在 CSS 中使用沿着路径运动,你需要将路径数据传递给
offset-path
属性,就像这样:我通常会在 Illustrator 中创建 SVG,然后使用 SVGOMG 进行优化,以获取路径数据。
在这个例子中,我希望动画对象沿着路径从起点运动到终点,并且路径是一个闭合路径,因为路径数据末尾有一个
z
。这意味着路径是一个循环,所以这个小生物最终会回到起点。我在关键帧中设置了这些参数,只指定了100%
的值,因为默认值为0
:然后,将动画应用于元素:
替代方案:GreenSock 的沿着路径运动
如果你想要最广泛的浏览器支持和最灵活的实现方式,那么你应该使用 GreenSock。GSAP 的 Bezier 插件(默认情况下包含在 TweenMax 中)支持 IE7 及更高版本(非 SVG 元素),以及 IE9 及更高版本(SVG 元素),这是目前最广泛的 SVG 动画支持。它在移动设备上也运行得很好。
我之前在 David Walsh 博客上 写过关于这个插件的文章,但这里只是简要回顾一下,并介绍一些自那以后发布的新功能:
最初,你需要传递一个值数组:
但正如你所看到的,你还可以选择自动旋转(或不旋转),就像 SMIL 的
rotate
属性一样。如果你想使用 SMIL 中的auto-reverse
或auto:n
参数来指定旋转的初始位置或旋转角度,GSAP 允许你使用rotation:90
来更改旋转角度,或者如果你需要更精细的控制,可以使用更具体的设置:在 SMIL 中,你可以对路径或组进行变换,以改变动画对象在运动过程中的方向。在 GSAP 中,你可以通过
autoRotate: false
轻松实现这一点,并使用set
初始化旋转。你也可以像在 SMIL 中一样,在 SVG 属性本身对元素进行变换,但这有点不太优雅,而且在工作时更难跟踪。你还可以将
type
属性设置为thru
、soft
、quadratic
或cubic
。有关这些属性的更多文档,请查看 GreenSock API 文档。thru
属性的一个很好的用途是能够影响元素的弯曲程度。如果你将这些点视为弹跳的坐标,那么弯曲程度将控制在这些点之间采取的路径的直接程度。0
表示直线路径,1
表示稍微松散的路径,2
表示一个漂亮的曲线,而3
及更高的值将开始在自身上缠绕。最近,GreenSock 也提供了将路径数据传递给 CSS 和 SMIL 模块的能力,就像使用原生 SMIL 一样。这作为他们 MorphSVG 插件的扩展,因此你需要添加该插件,并像这样使用它:
默认情况下,会将我要进行动画的组(在本例中为
#lil-guy
)的左上角与路径轨迹对齐。这会导致视觉上的错位。因此,我使用TweenLite.set
将#lil-guy
设置为使用中心点:你还可以通过将一个对象作为该方法的第二个参数传递,并在
pathDataToBezier
中定义offsetX
和offsetY
来偏移这些路径,注意,你可能需要扩展viewBox
,以确保你正在进行动画的组或属性不会被裁剪掉。你甚至可以为这个定位定义一个矩阵坐标。
另一个选择是将
align
属性设置为“relative”
。这将防止动画对象跳跃,因为它会保持每个坐标相对于x:0
和y:0
的位置。在之前的示例中,我使用align
将运动与#lil-guy
组本身配对。有关 GreenSock 的 Bezier 插件 API 中这个新功能(新是指在本文发布之日新发布的功能!)的更多信息,请查看他们的 文档,以及这个 很棒的解释视频。
🎭 形状变形
以前,你可以将路径数据作为值传递给
animate
属性,以使形状变形。Noah Blon 有一个很好的例子:替代方案:Snap.svg 或 SVG Morpheus
一些库提供了变形路径或形状值,例如 Snap.svg 和 SVG Morpheus,但需要注意的是(即使在 SMIL 中也是如此),形状必须具有相同数量的点,否则变形看起来很糟糕,或者完全失败。这在预处理方面令人失望,因为这意味着你必须仔细跟踪你正在制作的内容,或者与你的设计师良好协作,以确保你获得这些(有时是任意的)中间点数据。额外的点也会不必要地膨胀你的代码。
替代方案:GreenSock MorphSVG
我强烈推荐 GSAP 的 MorphSVG 插件,因为它可以很好地变形具有不同数量点的形状和路径。请查看本网站徽标上的切换按钮,以演示变形的效果。这里还有另一个例子:
因为 MorphSVG 插件可以对路径数据进行动画处理,所以如果你需要转换形状,可以使用他们的
convertToPath
选项:这使我们能够进行非常复杂的形状动画,并且是 Web 上所有运动的改变者。
这个插件还提供了一些额外的功能,使其更加出色。第一个是实用程序插件
findShapeIndex
。假设你对形状的变形方式不满意(虽然十有八九自动预设会正常工作),你可以加载该插件(别担心,你不需要在生产中添加额外的重量,因为它不需要),并将两个值传递给它:要进行动画的第一个形状的 ID 和第二个形状的 ID。一个 GUI 会弹出,你可以在其中切换值,它还会自动使用repeat: -1
,以便它会不断地在形状之间循环。一旦你有了这个额外的值,你就可以在
morphSVG
对象中传递shapeIndex
:第二个额外的功能是该插件能够解析剪切路径,这是其他库无法提供的。最后,你还可以重用第一个起始 ID(而不是必须存储该路径数据以供重用)。值得一提的是,当该插件首次发布时,这些功能不可用,但 GreenSock 认识到需要支持这些功能,因此将其包含在内。
现在,我们不再受限于指定的点数,我们拓宽了各种效果的可能性。下面,我制作了一些烟雾:
🖱️ DOM 事件
SMIL 中很好地集成了诸如悬停和点击之类的事件。为了启动动画,可以指定
begin="click"
或begin="hover"
。替代方案:JavaScript
有像
onmouseenter
和onmouseleave
这样的原生 DOM 事件,用于悬停,以及click
事件,用于点击。你可以使用它们来更改事件触发器,从而触发基于 JavaScript 的动画。替代方案:JavaScript + CSS
你可以使用 JavaScript 来更改类名或直接更改 CSS 样式。以下是一种可能性:更改
animation-play-state
以从事件触发器启动动画。或者在 jQuery 中:
这种实现不会像 SMIL 示例那样立即将动画重置到开头。如果你想实现这一点,CSS-Tricks 上的一篇之前的文章详细介绍了几种实现方法。
替代方案:Greensock
在 GSAP 中,重启更加简单。我们可以将动画添加到时间线中,将其设置为暂停,然后在点击时重启它。这种实现更接近你对 SMIL 的预期,因为我们不需要做任何 hacky 的事情,比如克隆/重新插入 DOM 节点或更改元素上设置的任何属性。
⏱️ 在“Y”完成后运行“X”
SMIL 还允许更复杂的时间事件,例如
begin="circ-anim.begin + 1s"
。这在链接动画时特别有用。替代方案:CSS
在 CSS 中,我们可以通过在第二个值上设置延迟来链接动画:
这种方法有点令人沮丧,因为你必须确保记住更改第一个间隔以及延迟。
替代方案:CSS 预处理
如果我们使用(例如)Sass 中的变量,维护和管理这些间隔会更容易:
现在我们知道,如果我们更新一个值,它们将保持同步。
但是,如果我们想始终检测动画何时完成,JavaScript 提供了一些不错的原生功能,比如
animationEnd
:🕰️ 计时器
SMIL 还提供了一个
set
属性,它允许你设置一个计时器,以便在指定的时间后执行某些操作。替代方案:JavaScript
我们可以使用
setTimeout
来实现相同的行为。替代方案:GreenSock
GreenSock 提供了
delay
属性,可以实现相同的效果。🔄 循环
SMIL 允许你通过
repeatCount
属性来控制动画的循环次数。替代方案:CSS
在 CSS 中,你可以使用
animation-iteration-count
属性来控制动画的循环次数。infinite
值意味着动画将无限循环。你也可以指定一个具体的数字,例如animation-iteration-count: 3
,表示动画将循环三次。替代方案:GreenSock
GreenSock 提供了
repeat
属性,可以实现相同的行为。repeat: -1
表示动画将无限循环。你也可以指定一个具体的数字,例如repeat: 3
,表示动画将循环三次。🎬 动画组
SMIL 允许你使用
animate
元素来创建动画组,并通过begin
属性来控制组内动画的执行顺序。替代方案:CSS
在 CSS 中,你可以使用
animation-delay
属性来控制动画的延迟时间。这种方法有点令人沮丧,因为你必须确保记住更改第一个间隔以及延迟。
替代方案:CSS 预处理
如果我们使用(例如)Sass 中的变量,维护和管理这些间隔会更容易:
现在我们知道,如果我们更新一个值,它们将保持同步。
替代方案:GreenSock
GreenSock 提供了
TimelineLite
类,可以用来创建动画组,并通过delay
属性来控制组内动画的执行顺序。+=1
表示第二个动画将在第一个动画完成 1 秒后开始。总结
SMIL 曾经是 SVG 动画的王者,但随着浏览器支持的减少,我们不得不寻找其他替代方案。幸运的是,CSS、JavaScript 和 GreenSock 等工具提供了强大的功能,可以让我们实现 SMIL 中的所有功能,甚至更多。
选择哪种方法取决于你的需求和偏好。如果你需要最广泛的浏览器支持,那么 GreenSock 是一个不错的选择。如果你更喜欢使用 CSS,那么 CSS 动画是一个不错的选择。如果你需要更灵活的控制,那么 JavaScript 是一个不错的选择。
无论你选择哪种方法,都希望你能够轻松地创建出令人惊叹的 SVG 动画!
参考文献