内容提要
SMIL是一种无需JavaScript即可在SVG中实现动画的方法,尤其适用于`<img>`标签。文章介绍了使用时间图表规划SMIL动画,通过同步基值(如`begin="other.end"`)控制动画时序,并以三圆点加载动画为例,展示如何通过调整动画开始时间创造不同视觉效果,同时提及尊重`prefers-reduced-motion`偏好。
延伸解读
SMIL 的适用场景与限制
SMIL 动画无需 JavaScript,可在 <img> 标签中运行,适合需要嵌入 SVG 动画但无法使用脚本的场景。然而,每个 <animate> 标签只能针对一个元素的一个属性,导致代码冗长。相比 CSS 动画,SMIL 在复杂动画中可能更繁琐,但在某些属性(如 viewBox)尚无 CSS 替代时,SMIL 仍是必要选择。
同步基值(syncbase)的实用技巧
使用 syncbase 值(如 begin="other.end - 300ms")可以精确控制动画间的相对时序,避免手动计算绝对时间。通过指定主动画,其他动画可同步到其 begin 或 end,便于整体调整。注意负偏移可能导致动画在文档加载前开始,浏览器会跳至相应状态,需确保有足够时间完成动画。
尊重用户减少动态偏好
实现 SMIL 动画时,应尊重 prefers-reduced-motion 设置。文章提供了多种方案:使用 <picture> 元素根据媒体查询切换静态图、在 SVG 内用 CSS 媒体查询隐藏动画、或使用 CSS background-image 配合媒体查询。选择适合的方案可避免后期重写,并提升可访问性。
时间图表的价值
时间图表通过线段可视化动画的开始和结束时间,帮助规划复杂动画的时序,尤其当动画包含多个元素和属性时。它不要求精确比例,只需清晰展示相对顺序。绘制图表能发现时序模式,便于比较不同版本,并简化后续维护。该方法不仅适用于 SMIL,也可用于 CSS 动画规划。
Q&A
SMIL是什么?它有什么优势?
SMIL(Synchronized Multimedia Integration Language)是一种无需JavaScript即可在SVG中实现动画的方法。它的优势在于可以在<img>标签中正常工作,并且能够完全动画化SVG中的所有内容,而不需要JavaScript。
如何使用时间图表规划SMIL动画?
时间图表是一种用线段表示动画开始和结束时间的工具。绘制时,每个组件动画用一条线段表示,标记开始和结束,并标注持续时间。通过排列这些线段,可以直观地看到动画各部分如何随时间级联,从而帮助规划动画的时序。
什么是syncbase值?在SMIL中如何使用?
syncbase值是SMIL中用于同步动画开始时间的一种方法,格式为“元素ID.begin”或“元素ID.end”,可加正负偏移。例如,`begin="colorChange.end - 300ms"`表示在colorChange动画结束前300毫秒开始。这使动画之间的相对时序变得明确。
如何尊重prefers-reduced-motion偏好?
有多种方法:使用<picture>元素配合媒体查询提供静态版本;在SVG内使用CSS @media查询切换显示;使用CSS背景图并包裹在媒体查询中;使用SVG的<view>元素;或使用JavaScript的matchMedia()和SMIL DOM接口控制动画。文章建议根据具体场景选择合适的方法。
在SMIL中,如何通过改变动画开始时间来创造不同的视觉效果?
通过调整syncbase值的偏移或改变动画之间的依赖关系,可以改变动画的节奏和顺序。例如,在三圆点加载动画中,将淡出动画的开始时间从fadeInRight.end改为fadeInMiddle.end,会改变视觉上的连贯性。时间图表可以帮助比较不同版本的效果。
SMIL动画的局限性是什么?
SMIL标记容易膨胀,因为每个<animate>标签只能针对一个元素的一个属性,导致代码量比CSS或JavaScript多。此外,syncbase值仅适用于SMIL,不适用于其他动画方法。
在SMIL中,如何使用<set>标签重置动画属性?
当使用fill="freeze"时,动画结束后属性保持最终值。为了重置属性,可以使用<set>标签,它没有持续时间,立即设置属性值。例如,`<set href="#leftDot" attributeName="fill-opacity" to="0" begin="fadeOutLeft.end" fill="freeze" />`会在指定时间重置fill-opacity。
在SMIL中,如何实现循环动画?
通过设置begin属性为多个时间值,例如`begin="0s; fadeOutLeft.end"`,可以在动画结束后重新开始。也可以使用syncbase值将循环的结束与另一个动画的开始关联,实现循环。