跳转到内容

svg 实现文字适应纹理

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

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 刀刀 刀刀

页面历史

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