使用SVG和裁剪实现文字斑点动画
原文: Animate a Blob of Text with SVG and Text Clipping
作者: Zach Saucier
大致思路是用SVG做背景,SVG text做裁切路径。使用SVG而不是用CSS裁剪图像,是因为要实现背景动画的话CSS就需要一个gif的动态图片。
首先需要创建一个由SVG图形组成的背景。这里使用椭圆形斑点的形状。需要注意的是将矢量图软件中的画板/画布大小设置成和最终效果里的viewBox
相同的尺寸。(Inkscape中在文档属性下的缩放选项)
目标是用各种各样的形状覆盖画板的大部分位置,最好有一些形状互相重叠。
接着在<clipPath>
中添加一些文字,把组成背景的路径聚集在一个<g>
元素中,并在上面应用CSSclip-path
属性,将文字作为显示的剪切区域。代码如下:
<svg viewbox="0 0 700 225">
<clipPath id="textClip" class="filled-heading">
<text y="70">We are</text>
<text y="140">Creators</text>
<text y="210">+Innovators</text>
</clipPath>
<g id="background" clip-path="url(#textClip)">
<path d="m449.78..." />
</g>
</svg>
目前为止还没有给背景添加动画,因此得到的效果只是一些纯文字的样式。
那么动效如何实现?可以使用一些简单的CSS动画:
/* 背景图形动画 */
#background path {
animation: pulse 4s cubic-bezier(0.455, 0.030, 0.515, 0.955) infinite;
/* 让SVG对象缩放时保持原来的位置 */
transform-origin: 50% 50%;
transform-box: fill-box;
}
@keyframes pulse {
/* 缩放的同时增加一些旋转角度,效果会更有趣 */
0%, 100% { transform: scale(0) rotate(33deg); }
35%, 65% { transform: scale(1) rotate(0deg); }
}
注: 一般html元素中的
transform-origin
是相对元素本身,SVG元素中的是相对于SVG画布,所以这里设定transform-box: fill-box;
让path在旋转缩放时候位置不变,参考: Transforms on SVG Elements
需要注意的是 transform-box: fill-box;
属性IE浏览器不支持,所以要兼容IE的话可以参考这里:javascript - SVG Scale without moving location - Stack Overflow
可以使用文字编辑器或矢量软件给图形绘制(指定)颜色,但是动态生成的颜色会更有意思。比如:
// 定义颜色数组
const colors = ['#f5a147','#51cad8','#112b39'];
// 选择SVG路径
var blobs = document.querySelectorAll("path");
// 随机填充颜色
blobs.forEach(blob => {
blob.style.fill = colors[Math.floor(Math.random() * colors.length)];
});
为了在每次循环中改变文字内容,首先要把它们都添加到SVG clipPath中
<clipPath id="text" class="filled-heading">
<text y="70">We are</text>
<text y="140">Creators</text>
<text y="210">+Innovators</text>
<text y="70">We are</text>
<text y="140">Movers</text>
<text y="210">+Shakers</text>
<text y="70">We are</text>
<text y="140">Stylish</text>
<text y="210">+Techy</text>
</clipPath>
然后可以使用CSS或者JavaScript指定文字的展示顺序。不幸的是我们不能用<g>
元素来包裹<text>
,因为它在clipPath
中并没什么卵用。这里将它们分割为三个CSS动画,每组包含三个路径:
/* 路径 1-3 */
#textClip text:nth-of-type(n + 1):nth-of-type(-n + 3) {
animation: showFirst 12s infinite;
}
/* 路径 4-6 */
#textClip text:nth-of-type(n + 4):nth-of-type(-n + 6) {
animation: showSecond 12s infinite;
}
/* 路径 7-9 */
#textClip text:nth-of-type(n + 7):nth-of-type(-n + 9) {
animation: showThird 12s infinite;
}
@keyframes showFirst {
0%, 33% {
opacity: 1;
}
33.0001%, 100% { opacity: 0; }
}
@keyframes showSecond {
33.0001%, 66% {
opacity: 1;
}
0%, 33%, 66.0001%, 100% { opacity: 0; }
}
@keyframes showThird {
66.0001%, 99.999% {
opacity: 1;
}
0%, 66%, 100% { opacity: 0; }
}
效果:
在此基础上做一些更有趣的事:
Demo 1: 使用Inkscape工具创建一些随机图形并填充颜色,色卡可以使用颜色生成工具Re: Pleasing Color Palettes,这里选择了palx:
Demo 2: 复制文字来使用 例子
Demo 3: 或者让背景图形旋转:
Demo 4: 使用CSS或者JavaScript在文字变化时改变颜色:
Demo 5: 给<text>
添加x="50%" text-anchor="middle"
属性可以使文字水平居中(栗子),因为是多行文本,所以垂直居中可能需要更多设置。
由于使用了SVG,这个效果自身就是响应式的,缩放不变形简直棒棒哒。
最后,还有人用另一个方法实现了同样效果 传送门。
里面动画更多是用JavaScript实现