CSS & SVG foreignObject 实现文字镂空波浪动画

简介: CSS & SVG foreignObject 实现文字镂空波浪动画

之前看过一篇文章:CSS 奇技淫巧 | 妙用混合模式实现文字镂空波浪效果,非常巧妙,将 CSS 动画融入文本内部,主要利用了混合模式,效果是这样的


image.png

为什么要用到混合模式呢?因为这是文本,文本内部不可能放入 HTML 节点,所以下面介绍将另一种方式,在 HTML 完全受限的情况下,借助 SVG foreignObject 也能很轻松的实现这一效果,而且会有更好的效果,一起看看吧


一、SVG foreignObject 是什么


首先, foreignObjectSVG 中的一个元素,允许包含来自不同的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,然后放到浏览器中


image.png

注意到SVG 有个属性xmlns,这个就是命名空间,它规定这段内容在浏览器中是如何渲染的,这里的http://www.w3.org/2000/svg 就是 SVG 的命名空间。假如没有这个属性,浏览器中就直接以普通 xml 文档渲染了,如下


image.png

不过有一种情况可以不用指定这个命名空间:如果我们的SVG文件是直接内联在XHTML页面中或者直接以.html作为后缀名,是可以不指定命名空间的,浏览器会自动识别。


image.png

那么,回到这里,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的命名空间,渲染结果如下


image.png

和普通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


image.png

一般情况下,我们都可以把 SVG 当做一种图片,可以很方便地用在网页中的各种地方,比如 imgsrc属性,或者直接当做 CSS 背景图片。简单一句话,借助 foreignObject,可以很轻易地将一段 HTML 转换为图片,包括 CSS 动画


这样就有趣了,很多受 HTML 结构限制的场景就可以用这种方式解决了,比如文章开头提到的文本镂空波浪动画


二、文本背景图片


在文本中嵌入背景图是有固定套路的,借助-webkit-background-clip裁切和透明文字,可以轻易的将任意背景置入文字中,例如

<p>CSS TEXT</p>
p{
    -webkit-background-clip: text;
    color: transparent;
      background: linear-gradient( #f44336, #ffc107);
}


效果如下


image.png

试想一下,如果上面的波浪动画做成了一张图片,是不是可以直接用在这里?

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);
  }
}


可以得到这样的效果


image.png

然后将这个放入一个 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,在浏览器中就可以直接打开预览了!


image.png

这样就得到了一张“动图”


四、SVG 图片的使用


回到前面的文本,直接将渐变改为这张图就可以了

p{
      -webkit-text-stroke: 1px #333;
    -webkit-background-clip: text;
    color: transparent;
      background: url(wave.svg);
}


效果如下


image.png

当然,你也可以将这段 SVG 直接转成 base 64 格式(推荐大家使用张鑫旭老师的 SVG 转换工具 ,非常赞)


image.png

转换完就是这样,完全没有任何依赖了(依稀还能看得明白)

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:'')


image.png

完整代码可以访问 CSS wave text (codepen.io)点击预览


五、优势和局限


优势其实非常明显,由于是图片,属于真正的文字镂空效果,因此不会像混合模式那样,容易受到背景图层的影响(原文实现只能是白色背景),比如这里换一种颜色


image.png

局限是由于变成了图片,某些属性样式就固定下来了,无法动态修改,hover相关交互也失效了,也无法控制动画的快慢等等(直接在页面中使用 SVG 是可以的)


六、其他应用


很多 HTML 严格受限的情况下都可以采用这种方式来实现,比如有时候伪元素不够了怎么办,完全可以用 SVG 来生成,这样你就有无数的伪元素可用了。


另外还有一个非常重要的应用场景,纯前端截图功能,大名鼎鼎的前端截图库rasterizeHTML就是这个原理


image.png

七、总结和说明


以上就是本文的全部内容了,一个还算实用的小技巧,稍微借助了 SVG 的一点点特性,主要是为了解决 HTML 结构限制的问题,剩下的还是传统 CSS 相关,这里总结一下


  1. SVG foreignObject 可以嵌入 HTML 标签
  2. 注意 SVG 和 HTML 的命名空间,HTML 中会自动识别
  3. 文本背景图片用 -webkit-background-clip 结合透明文字实现
  4. SVG 本质就是一种图片
  5. SVG 可以转义成内联 base 64,不影响原有动画
  6. SVG 在用作图片时,不支持动态修改样式
  7. SVG foreignObject 可以实现截图功能


很多时候,如果有图片相关需求时,都可以朝 SVG 的方向思考,毕竟 SVG 是一门图像语言,关于 SVG 有用的特性还有很多很多,后面会慢慢介绍的。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤

相关文章
|
1月前
|
机器学习/深度学习 前端开发 JavaScript
|
16天前
|
前端开发 搜索推荐 UED
实现 CSS 动画效果的兼容性
【10月更文挑战第16天】实现 CSS 动画效果的兼容性需要对不同浏览器的特性有深入的了解,并采取适当的策略和方法。通过不断的实践和优化,你可以在各种浏览器上创造出流畅、美观且兼容的动画效果,为用户带来更好的体验。在实际开发中,要密切关注浏览器的发展动态,及时掌握最新的兼容性技巧和解决方案,以确保你的动画设计能够在广泛的用户群体中得到良好的呈现。
|
5天前
基于CSS3 SVG实现带表情的投票打分源码
投票打分插件是基于CSS3和SVG的,它的特点是对于不同的评级会有不同的表情,比如1星是失落的表情,5分是帅酷的表情
13 3
|
21天前
|
前端开发 JavaScript API
探索 CSS Houdini:轻松构建酷炫的 3D 卡片翻转动画
本文通过构建一个 3D 翻卡动画深入探讨了 CSS Houdini 的强大功能,展示了如何通过 Worklets、自定义属性、Paint API 等扩展 CSS 的能力,实现高度灵活的动画效果。文章首先介绍了 Houdini 的核心概念与 API,并通过构建一个动态星空背景、圆形进度条以及交互式 3D 翻卡动画的实际示例,展示了如何利用 CSS Houdini 赋予网页设计更多创造力。最后,还演示了如何将这种 3D 翻卡效果集成到公司网站中,提升用户体验。CSS Houdini 的创新能力为网页设计带来了前所未有的灵活性,推动了前端开发迈向新的高度。
21 0
探索 CSS Houdini:轻松构建酷炫的 3D 卡片翻转动画
|
2月前
|
前端开发
前端基础(五)_CSS文本文字属性、背景颜色属性
本文详细介绍了CSS中关于文本和背景颜色的样式属性。包括字体大小、字体族、字体加粗、字体样式、文本行高、`font`属性、文本颜色、文本对齐方式、文本装饰线、首行缩进等文本属性,以及背景颜色、背景图片、背景重复、背景位置等背景属性。文章通过示例代码展示了这些属性的具体应用和效果。
28 3
前端基础(五)_CSS文本文字属性、背景颜色属性
|
2月前
|
JavaScript 前端开发
JS配合CSS3实现动画和拖动小星星小Demo
本文通过代码示例展示了如何使用JavaScript和CSS3实现动画效果和拖动小星星的交互效果,包括文字掉落动画和鼠标拖动产生小星星动画的实现方法。
41 0
JS配合CSS3实现动画和拖动小星星小Demo
|
1月前
|
前端开发
CSS 动画介绍及语法
CSS 动画介绍及语法
27 0
|
1月前
|
Web App开发 前端开发 iOS开发
|
3月前
|
前端开发
2s 利用 HTML+css动画实现企业官网效果
2s 利用 HTML+css动画实现企业官网效果
HTML+CSS 实现通用的企业官网页面(记得收藏)
HTML+CSS 实现通用的企业官网页面(记得收藏)