共计 4830 个字符,预计需要花费 13 分钟才能阅读完成。
之前看过一篇文章:CSS 奇技淫巧 | 妙用混合模式实现文字镂空波浪成果,十分奇妙,将 CSS 动画融入文本外部,次要利用了混合模式,成果是这样的
为什么要用到混合模式呢?因为这是文本,文本外部不可能放入 HTML 节点,所以上面介绍将另一种形式,在 HTML 齐全受限的状况下,借助 SVG foreignObject 也能很轻松的实现这一成果,而且会有更好的成果,一起看看吧
一、SVG foreignObject 是什么
首先,foreignObject 是 SVG
中的一个元素,容许蕴含来自不同的 XML 命名空间的元素。在浏览器的上下文中,个别是 XHTML / HTML
。什么意思呢?比方通常咱们在各种设计软件中导出的 SVG
可能是这样
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.1785 10.9999C2.1785 6.12799..." fill="#7A7A7A"/>
</svg>
如果间接另存为 map.svg,而后放到浏览器中
留神到 SVG
有个属性xmlns
,这个就是 命名空间,它规定这段内容在浏览器中是如何渲染的,这里的http://www.w3.org/2000/svg
就是 SVG
的命名空间。如果没有这个属性,浏览器中就间接以一般 xml
文档渲染了,如下
不过有一种状况能够不必指定这个命名空间:如果咱们的 SVG 文件是间接内联在 XHTML 页面中或者间接以 .html
作为后缀名,是能够不指定命名空间的,浏览器会自动识别。
那么,回到这里,foreignObject 能够干什么呢?置信你曾经猜到了,就是能够在 SVG
外部渲染 HTML
标签!具体的做法就是,给foreignObject 外部加上 xml
的命名空间就能够了,例如
<svg xmlns="http://www.w3.org/2000/svg">
<foreignObject width="100%" height="100%">
<body xmlns="http://www.w3.org/1999/xhtml">
<style>
p{color: red}
</style>
<p>xboxyan</p>
</body>
</foreignObject>
</svg>
留神,body
标签有一个属性 xmlns="http://www.w3.org/1999/xhtml"
,这个就是html
的命名空间,渲染后果如下
和一般 HTML 简直一样,上面重点来了,还能再加一些 CSS 动画
<svg xmlns="http://www.w3.org/2000/svg">
<foreignObject width="100%" height="100%">
<body xmlns="http://www.w3.org/1999/xhtml">
<style>
p{
color: red;
animation: hue 5s infinite
}
@keyframes hue{
to {filter: hue-rotate(1turn)
}
}
</style>
<p>xboxyan</p>
</body>
</foreignObject>
</svg>
这样就失去了一个有动画的 SVG
个别状况下,咱们都能够把 SVG 当做一种图片,能够很不便地用在网页中的各种中央,比方 img
的 src
属性,或者间接当做 CSS 背景图片。简略一句话,借助 foreignObject
,能够很轻易地将一段 HTML 转换为图片,包含 CSS 动画。
这样就乏味了,很多受 HTML 结构限制的场景就能够用这种形式解决了,比方文章结尾提到的文本镂空波浪动画
二、文本背景图片
在文本中嵌入背景图是有固定套路的,借助 -webkit-background-clip
裁切和通明文字,能够轻易的将任意背景置入文字中,例如
<p>CSS TEXT</p>
p{
-webkit-background-clip: text;
color: transparent;
background: linear-gradient(#f44336, #ffc107);
}
成果如下
试想一下,如果下面的波浪动画做成了一张图片,是不是能够间接用在这里?
p{
-webkit-background-clip: text;
color: transparent;
background: url(wave.svg);
}
三、CSS 动画 转 SVG 图片
假如咱们曾经实现这样一个波浪动画(本文重点不在这),具体原理能够参考 coco 的文章纯 CSS 实现波浪成果,这里略微做了批改
body::before, body::after {
content: "";
position: absolute;
bottom: 50%;
left: 50%;
width: 400vw;
height: 400vw;
border-radius: 45% 48% 43% 47%;
transform: translate(-50%, 0);
box-shadow: 0 0 0 50vw #54caff9e;
animation: rotate 10s infinite linear;
}
body::after {
border-radius: 43% 47% 44% 48%;
animation: rotate 10s infinite -1s linear;
}
@keyframes rotate {
0% {transform: translate(-50%, 0) rotate(0);
}
100% {transform: translate(-50%, 0) rotate(360deg);
}
}
能够失去这样的成果
而后将这个放入一个 SVG foreignObject 中,就变成了这样
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<foreignObject width="100%" height="100%">
<style>
html,body{
width: 100%;
height: 100%
}
body{
margin: 0;
background:transparent;
transition: .3s;
}
body::before, body::after {
content: '';
position: absolute;
bottom: 50%;
left: 50%;
width: 400vw;
height: 400vw;
border-radius: 45% 48% 43% 47%;
transform: translate(-50%, 0);
box-shadow: 0 0 0 50vw #54caff9e;
animation: rotate 10s infinite linear;
}
body::after {
border-radius: 43% 47% 44% 48%;
animation: rotate 10s infinite -1s linear;
}
@keyframes rotate {
0% {transform: translate(-50%, 0) rotate(0);
}
100% {transform: translate(-50%, 0) rotate(360deg);
}
}
</style>
<body xmlns="http://www.w3.org/1999/xhtml">
</body>
</foreignObject>
</svg>
将这段 SVG 另存为 wave.svg
,在浏览器中就能够间接关上预览了!
这样就失去了一张“动图”
四、SVG 图片的应用
回到后面的文本,间接将突变改为这张图就能够了
p{
-webkit-text-stroke: 1px #333;
-webkit-background-clip: text;
color: transparent;
background: url(wave.svg);
}
成果如下
当然,你也能够将这段 SVG 间接转成 base 64 格局(举荐大家应用张鑫旭老师的 SVG 转换工具,十分赞)
转换完就是这样,齐全没有任何依赖了(依稀还能看得明确)
p{
-webkit-text-stroke: 1px #333;
-webkit-background-clip: text;
color: transparent;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3CforeignObject width='100%25'height='100%25'%3E%3Cstyle%3E@keyframes rotate%7B0%25%7Btransform:translate(-50%25,0) rotate(0)%7Dto%7Btransform:translate(-50%25,0) rotate(360deg)%7D%7Dbody%7Bwidth:100%25;height:100%25;margin:0;background:0 0;transition:.3s%7Dbody::after,body::before%7Bcontent:'';position:absolute;bottom:50%25;left:50%25;width:400vw;height:400vw;border-radius:45%25 48%25 43%25 47%25;transform:translate(-50%25,0);box-shadow:0 0 0 50vw %2354caff9e;animation:rotate 10s infinite linear;z-index:1%7Dbody::after%7Bborder-radius:43%25 47%25 44%25 48%25;animation:rotate 10s infinite -1s linear%7D%3C/style%3E%3Cbody xmlns='http://www.w3.org/1999/xhtml'/%3E%3C/foreignObject%3E%3C/svg%3E");
}
这样也是齐全没问题的(如果预览有误,有可能是 CSS 中的单双引号问题,比方 content:”)
残缺代码能够拜访 CSS wave text (codepen.io)
五、劣势和局限
劣势其实非常明显,因为是图片,属于真正的文字镂空成果,因而不会像混合模式那样,容易受到背景图层的影响(原文实现只能是红色背景),比方这里换一种色彩
局限是因为变成了图片,某些属性款式就固定下来了,无奈动静批改,hover
相干交互也生效了,也无法控制动画的快慢等等(间接在页面中应用 SVG 是能够的)
六、其余利用
很多 HTML 严格受限的状况下都能够采纳这种形式来实现,比方有时候伪元素不够了怎么办,齐全能够用 SVG 来生成,这样你就有有数的伪元素可用了。
另外还有一个十分重要的利用场景,纯前端截图性能,赫赫有名的前端截图库 rasterizeHTML 就是这个原理
七、总结和阐明
以上就是本文的全部内容了,一个还算实用的小技巧,略微借助了 SVG 的一点点个性,次要是为了解决 HTML 结构限制的问题,剩下的还是传统 CSS 相干,这里总结一下
- SVG foreignObject 能够嵌入 HTML 标签
- 留神 SVG 和 HTML 的命名空间,HTML 中会自动识别
- 文本背景图片用 -webkit-background-clip 联合通明文字实现
- SVG 实质就是一种图片
- SVG 能够本义成内联 base 64,不影响原有动画
- SVG 在用作图片时,不反对动静批改款式
- SVG foreignObject 能够实现截图性能
很多时候,如果有图片相干需要时,都能够朝 SVG 的方向思考,毕竟 SVG 是一门图像语言,对于 SVG 有用的个性还有很多很多,前面会缓缓介绍的。最初,如果感觉还不错,对你有帮忙的话,欢送点赞、珍藏、转发❤❤❤