type
status
date
slug
summary
category
tags
password
icon
notion image
当我收到一个需求,要求做出如上图一样的文字摇曳的SVG,我的脑子里闪过svg、path、group、text……等等SVG的标签,这太让人崩溃了。
SVG多麻烦,难道不能用div+css动画来做吗?SVG有没有兼容前端开发习惯的写法呢?
诶,还真有,SVG的 <foreignObject> 元素就支持在里面写HTML和CSS。
欢迎加入「🌍独立全栈开发交流群」,一起学习交流前端和Node端技术

SVG与foreignObject

如果你看过SVG的代码,一定注意到了,每个SVG都有一个 xmlns="http://www.w3.org/2000/svg 这样的属性,这就是命名空间(namespace)。如果不给svg标签添加命名空间,那么浏览器会当作文本来识别,不信试试这两个SVG:
命名标签的作用是告诉浏览器应当以何种标准进行解析,SVG标签缺少命名空间的情况下默认不属于任何特定的语言或格式,所以浏览不会把它作为图形渲染,而是被视为普通的文本。
那么,<foreignObject> 又是从何而来,怎么使用?
<foreignObject> 是SVG 1.1规范中引入的一个元素,它允许在SVG文档中嵌入其他XML命名空间的元素,如:XHTML。这意味着开发者可以在SVG中使用HTML和CSS了。
它的用法是这样:
<div> 里指定命名空间在HTML5标准下不是必须的,但为了代码规范,仍然建议加上。

动画实现

知道了 <foreignObject> 的用法,我们就可以开始用 CSS + <foreignObject>的方式来实现我们想要的动画了。
主要有以下三项任务:
  • 背景动态渐变
  • 文字摇曳和淡入
  • 内容可配置

背景动态渐变

背景动态渐变的动画可以通过CSS关键帧(@keyframes)来实现。
  • animate-gradient 里面,animation 定义了 gradientBackground 的动画方式,infinite 表示无限重复
  • linear-gradient 定义了渐变颜色
  • background-size 放大,让可视区域的颜色更少,在动画推进的时候才会有更平滑却又强烈的视觉效果
  • 通过 @keyframes 定义一个动画 gradientBackground ,并给了周期位置变化
实现的效果如下:
notion image

文字摇曳和淡入

文字摇曳也通过CSS关键帧( @keyframes)来实现。
  • 通过 @keyframes 定义摇曳的角度
  • 通过 animation 定义文字摇曳动画效果,alternate 指示动画应该在每次迭代后改变方向
实现的效果如下:
notion image
留个作业:请完成底部小字的淡入效果。

内容可配置

我觉得这个动画卡片还是挺通用的,所以我决定做成可配置的组件。
我希望卡片大小、文字内容和一些重要的样式均可配置,TypeScript定义就出来了:
因为我个人项目使用的是Next.js和TailwindCSS,所以就导出个React组件。调整后的组件代码是这样:
配置还有可优化的地方,你可以复制代码按自己的需求进行改造。
如果你不用TailwindCSS,可以到我的源码仓库获取内联CSS版的组件

结语

学会了 <foreignObject> 知识,你还不赶紧炫一下自己的创意?
 
本文源码:👉AnimatedSvg
本文体验地址:👉在线演示
命名空间(namespace)基础:👉快速了解namespace

专栏资源

专栏介绍:分享CSS新特性和好看的样式设计
专栏地址:👉简明实用CSS技巧
 
CSS技巧:人人都能看懂的新拟态实现思路CSS技巧:用十行代码写一个跃动文字链的hover效果