跳转到内容

svg 实现文字适应纹理

刀刀
0字
0分钟
2026/8/16

SVG 需求背景

目前有一个需求,需要文字适应背景图片的纹理,且能实现文字内容颜色自定义转换的功能。

该功能乍一看不好实现,一般可以找设计师给 UI 图,但是无法适配纹理。因此还是需要回到前端自己实现,不过可以参考 UI 的实现思路——滤镜。

前端滤镜首先考虑 filter ,但是找遍 filter 所有属性值都无法实现。因此继续往下,想到了 SVG 的滤镜。

SVG 的滤镜效果更强大,可以说 CSSfilter 滤镜是 SVG 滤镜的子集,尝试。

SVG 滤镜

写一个 svg 标签,标签内放置一个图片 image 和一个文本 text ,代码:

html
<svg viewBox="0 0 600 330">
  <image
    href="./cat.png"
    x="0"
    y="0"
    width="100%"
    height="100%"
    preserveAspectRatio="none"
  ></image>
  <text
    x="50%"
    y="50%"
    font-size="10em"
    font-weight="bold"
    text-anchor="middle"
    alignment-baseline="middle"
    fill="#000"
  >
    Logo
  </text>
</svg>

其中设置了图片标签的 x 轴和 y 轴位置、宽高缩放设置,设置了文本的 x 轴和 y 轴位置、字体大小和粗细、横轴纵轴对齐方式、字体颜色。

现在需要添加纹理,由于是让文字适配背景,因此要给文字添加滤镜。滤镜添加在 svg 内,通过 defsfilter 标签实现,为 filter 设置唯一值 id ,然后为 text 绑定。代码如下:

html
<svg viewBox="0 0 600 330">
  <defs>
    <filter id="conform"></filter>
  </defs>
  <image
    href="./cat.png"
    x="0"
    y="0"
    width="100%"
    height="100%"
    preserveAspectRatio="none"
  ></image>
  <text
    x="50%"
    y="50%"
    font-size="10em"
    font-weight="bold"
    text-anchor="middle"
    alignment-baseline="middle"
    fill="#000"
    filter="url(#conform)"
  >
    Logo
  </text>
</svg>

现在刷新页面后文本内容不见了,这是必然的,因为 filter 内没设置任何东西,所以无效果,后续逐步实现。

SVG 文字效果

实现文字适配图片纹理,需要一个图片滤镜,设置图片的路径以及其 x 轴和 y 轴起始坐标。最后通过 result 导出一个名称 ORIGIN_IMAGE 给后续的滤镜使用。

html
<feimage
  href="./cat.png"
  result="ORIGIN_IMAGE"
  x="0"
  y="0"
  width="100%"
  height="100%"
  preserveAspectRatio="none"
>
</feimage>

图片不需要太多颜色,设置为灰度图,通过 in 引入上一个滤镜的名称,再通过 result 导出名称 GRAY_IMAGE 给下一个滤镜使用。

html
<feColorMatrix in="ORIGIN_IMAGE" type="saturate" values="0" result="GRAY_IMAGE">
</feColorMatrix>

接着为文字设置置换滤镜,其本质是改变文本里的每一个像素点。 in 引入原始图像 SourceGraphic (也就是 text 文本)和灰度图像 GRAY_IMAGE ,以灰度图作为参考,通过一个算法来实现偏移。该算法简言之:当参考点越黑,它就越往右下偏移;参考点越白它就越往左上偏移;不黑不白则不偏移。再通过 result 导出名称 TEXTURED_TEXT 给下一个滤镜使用。

html
<feDisplacementMap
  in="SourceGraphic"
  in2="GRAY_IMAGE"
  scale="15"
  xChannelSelector="R"
  yChannelSelector="R"
  result="TEXTURED_TEXT"
>
</feDisplacementMap>

让文字和图片纹理贴合,需要 in 引入 TEXTURED_TEXT 把图像再写一遍,让图像和文本融合。再通过 result 导出名称 BG 给下一个滤镜使用。

html
<feimage
  href="./cat.png"
  in="TEXTURED_TEXT"
  x="0"
  y="0"
  width="100%"
  height="100%"
  preserveAspectRatio="none"
  result="BG"
>
</feimage>

为滤镜添加不透明度,导出名称 OPACITY_TEXT

html
<feColorMatrix
  in="TEXTURED_TEXT"
  type="matrix"
  values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 9 0"
  result="OPACITY_TEXT"
>
</feColorMatrix>

得到不透明度的背景和融合成功的文本,把二者结合起来即可。

html
<feBlend in="BG" in2="OPACITY_TEXT" mode="multiply" result="BLENDED_TEXT">
</feBlend>

SVG 总体代码

点击查看代码
html
<template>
  <svg viewBox="0 0 600 330">
    <defs>
      <filter id="conform">
        <feimage
          href="./cat.png"
          result="ORIGIN_IMAGE"
          x="0"
          y="0"
          width="100%"
          height="100%"
          preserveAspectRatio="none"
        ></feimage>
        <feColorMatrix
          in="ORIGIN_IMAGE"
          type="saturate"
          values="0"
          result="GRAY_IMAGE"
        ></feColorMatrix>
        <feDisplacementMap
          in="SourceGraphic"
          in2="GRAY_IMAGE"
          scale="15"
          xChannelSelector="R"
          yChannelSelector="R"
          result="TEXTURED_TEXT"
        ></feDisplacementMap>
        <feimage
          href="./cat.png"
          in="TEXTURED_TEXT"
          x="0"
          y="0"
          width="100%"
          height="100%"
          preserveAspectRatio="none"
          result="BG"
        ></feimage>
        <feColorMatrix
          in="TEXTURED_TEXT"
          type="matrix"
          values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 9 0"
          result="OPACITY_TEXT"
        ></feColorMatrix>
        <feBlend
          in="BG"
          in2="OPACITY_TEXT"
          mode="multiply"
          result="BLENDED_TEXT"
        ></feBlend>
      </filter>
    </defs>
    <image
      href="./cat.png"
      x="0"
      y="0"
      width="100%"
      height="100%"
      preserveAspectRatio="none"
    ></image>
    <text
      x="50%"
      y="50%"
      font-size="10em"
      font-weight="bold"
      text-anchor="middle"
      alignment-baseline="middle"
      fill="orange"
      filter="url(#conform)"
    >
      Logo
    </text>
  </svg>
</template>

SVG 功能拓展

效果实现后,可以来点功能拓展,比如文本自定义、文本颜色自定义、背景图修改等。可自行尝试。

SVG 总体效果

跳转预览:点击跳转

贡献者

The avatar of contributor named as duyidao duyidao
The avatar of contributor named as v_duyilin v_duyilin
The avatar of contributor named as 平安喜乐 平安喜乐
The avatar of contributor named as 刀刀 刀刀

页面历史

刀刀博客累计访客 人;文档累计访问量共