Skip to content

svg绘制---花字篇

花字,这一种文字的样式在很多编辑软件都会看到它们的身影。最近笔主也是在做这一方面的需求,就顺道聊一聊这方面,可能你们的实现未必与我的一样,或许有更好的实现方法,让我们互相学习!😬😬😬

先看看花字是长什么样子的

下图是从某剪辑软件截图出来的😜

svg花字

一眼望过去,酷倒是挺酷的,但第一次做无从下手呀!于是就翻开了文档,一步一步来,先从最简单的开始嘛🤯🤯🤯

元素传送门🚪

属性传送门🚪

注意:下文只会贴出主要代码片段,都是基于以下 html 进行开发。

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>svg---花字</title>
  <style>
    html, body {
      margin: 0;
      padding: 0;
      background-color: #eee;
    }
  </style>
</head>
<body>
  
</body>
</html>

🙉🙉🙉首先先从最简单的开始,绘制一个文字,带颜色,带描边。

单描边填充花字

html
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <text
    x="10"
    y="60"
    fill="#FFBCD7"
    font-size="60"
    font-weight="900"
    stroke="#FF3F89"
    stroke-width="4"
    stroke-linejoin="round"
    font-family="WenYue-XinQingNianTi-NC-W8"
    paint-order="stroke"
  >
    花字
  </text>
</svg>

效果图👇👇👇(它就是第一张截图的第一个花字,因为电脑没有这个字体包,所以字体不一样)

svg花字

这里就先简单解释一下属性(大神请略过)😛

首先 <text> 标签表示绘制文字,还有rect 矩形、line 线 等等。详细请看元素传送门。

然后属性这里用到以下几个👇

  • fill 填充颜色,支持 16进制、rgb等。
  • font-size 字体大小,默认px
  • font-weight 字体粗细。
  • font-family 字体样式。
  • stroke 描边颜色,支持16进制、rgb等。
  • stroke-width 描边大小,默认 px
  • stroke-linejoin 转角处使用的形状。(上面使用了圆边)
  • paint-order 绘制顺序,默认先填充后描边。(上面使用了先描边再填充)

paint-order 解析

下图我把 1 分解成三个矩形,首先最外层到最里层(不包括最里层面积)是 stroke 的填充区域(蓝色箭头)中间层内部所有面积是 fill 的填充区域。最里层到中间层的宽度是stroke填充区域的一半,即最里黑边框到中间灰边框的距离。由此看来,normal 先填充再描边,就有一部分描边盖住 fill 填充区域,因此相对显示填充区域较小,描边较粗。反过来 stroke 是先描边后填充,就有一部分描边被 fill 填充区域盖住,因此相对显示填充区域较大,描边较细。

小技巧:如果当遇到一些字体无法加粗的情况下,但又想字体看起来粗一点,可以使用 stroke 顺序填充,不过如果要 stroke-width 看起来与之前一样粗细的话,需要乘二。

svg花字

学会了简单的填充和单描边文字后。咦~好像多描边文字不错哦!👊开干~~~

多描边花字

这里使用的方案是多个不同大小文字叠加在一起,达到多描边效果。

html
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <g
      font-size="60"
      font-weight="900"
      font-family="WenYue-XinQingNianTi-NC-W8"
      stroke-linejoin="round"
      paint-order="stroke"
    >
      <text x="10" y="60" fill="#C048C5" stroke="#C048C5" stroke-width="15">
        花字
      </text>
      <text x="10" y="60" fill="#7057CF" stroke="#7057CF" stroke-width="12">
        花字
      </text>
      <text x="10" y="60" fill="#86E431" stroke="#86E431" stroke-width="9">
        花字
      </text>
      <text x="10" y="60" fill="#FF865B" stroke="#FF865B" stroke-width="6">
        花字
      </text>
      <text x="10" y="60" fill="#FFFFFF" stroke="#FC3081" stroke-width="3">
        花字
      </text>
  </g>
</svg>

效果图👇👇👇

svg花字

这里使用了一个 <g> 元素,它用于分组,它包括的多个元素为一组,可以把公用的属性放置于 <g> 元素上,节省代码。

渐变花字

学了简单的填充,如果要渐变填充怎么办?

svg 里提供了一些渐变元素,如<linearGradient> 线性渐变, <radialGradient> 径向渐变等。

html
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
	<linearGradient id="linearFill" x1="0%" y1="0%" x2="0%" y2="100%">
	  <stop offset="0%" stop-color="#FF3A3A" />
	  <stop offset="100%" stop-color="#A80101" />
	</linearGradient>
  </defs>

  <text
	x="10"
	y="60"
	font-family="WenYue-XinQingNianTi-NC-W8"
	font-size="60"
	font-weight="900"
	fill="url(#linearFill)"
	stroke="#F8E8A2"
	stroke-width=".09em"
	paint-order="stroke"
  >
	花字
  </text>
</svg>

效果图👇👇👇

svg花字

解析⁉️

注意一点:id 必须必须必须唯一,否则会出现绘制错误或者闪烁消失的错误

svg 使用元素/滤镜主要通过 id 手段。因此需要特别注意!

  • defs 元素,是允许我们用来定义重复使用的图形元素,它不会呈现在界面上。
  • linearGradient 元素,定义线性渐变。x1x2y1y2 用来定义线性渐变的方向,简单理解可以把它们看成两个坐标点,然后相连形成的方向就是渐变方向。
  • <stop> 元素,用来定义一个渐变上的颜色坡度。(用于渐变元素内部)

投影花字

类似花字例子图片中的最后一个,我需要在花字后面加个阴影/投影。又该怎么做呢???

有两种方案

  1. 类似多描边花字那样,使用多个花字叠加,通过修改 xy 来错开位置,形成投影效果。
  2. 使用 filter 滤镜元素。这是一个非常重要的元素,熟悉它可以做出很多漂亮的花字。🤩🤩🤩

在这里主要展示的是第二种做法;第一种方案自己可以动手练一下,或者改一改 多描边花字的参数就知道怎么做了,所以在这里就不演示了。

html
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <defs>
	<filter id="filter">
	  <feDropShadow dx="2" dy="2" stdDeviation="0" flood-color="#EE4949" />
	</filter>
  </defs>
  <g
	dominant-baseline="text-after-edge"
	letter-spacing="0"
	font-family="WenYue-XinQingNianTi-NC-W8"
	font-size="60"
	font-weight="900"
	fill="#F7A4A4"
  >
	<text
	  x="10"
	  y="70"
	  stroke-width=".12em"
	  stroke="#F7A4A4"
	  stroke-linejoin="round"
	  filter="url(#filter)"
	>
	  花字
	</text>
	<text x="10" y="70" stroke-width=".04em" stroke="#FFF">花字</text>
  </g>
</svg>

效果图👇👇👇

svg花字

常规解析⁉️

这里实现的效果是双描边加投影,因此这里我使用了两个 text 元素叠加然后再使用一个 filter 滤镜。

在需要使用滤镜的元素上,通过 filter 属性指定滤镜元素。如 filter="url(#xxx)",即 使用 id 为 xxx 的滤镜。

  • filter 元素,作为原子滤镜操作的容器,不能直接呈现。
  • feDropShadow 元素,用于创建输入图形的投影,只能用于 filter 元素内部。
    • dx 属性表示 x 轴上的偏移。
    • dy 属性表示 y 轴上的偏移。
    • stdDeviation 属性表示投影的模糊度。
    • flood-color 属性表示投影颜色。
    • flood-opacity 属性表示不透明度。

纹理花字

纹理花字其实我们并不陌生,在 office 中也有该配置🙄

svg花字

本质原理就是利用一张图片当作颜色填充图形或文字

好像 <filter> 中也有 <feImage> 把图片作为滤镜,So give it a try!

feImage

  • feImage 元素,把图形数据作为像素数据输出。
    • href 属性表示对象的地址。xlink:href 也是一样效果,只不过不推荐使用了。

剩余那几个属性就不再多说了,公共属性来的。

html
<svg width="100%" height="100%" display="inline-block">
  <defs>
	<filter id="filter-img">
	  <feImage
		href="https://www.imgloc.com/images/2021/06/14/TWyQ.png"
		x="0"
		y="0"
		width="100"
		height="100"
	  />
	</filter>
  </defs>
  <g
	dominant-baseline="text-after-edge"
	letter-spacing="0"
	font-family="WenYue-XinQingNianTi-NC-W8"
	font-size="60"
	font-weight="900"
  >
	<text x="10" y="70" stroke="#9C4607" stroke-width=".04em" fill="#F7A4A4" filter="url(#filter-img)">
	  花字
	</text>
  </g>
</svg>

效果图👇👇👇

svg花字

🤔🤔🤔怎么好像不是我们想要的效果?分析一下代码,其实会发现这个花字是有显示的,只不过是滤镜盖住了。不难发现源头来自于 feImage ,它只是作为图像输出,并非与文字融合在一起,简单来说就是你想画一个文字,却又用一张图片覆盖在上面。

在文字不用 filter ,我直接使用 fill 呢?结果---还是不行。🤕🤕🤕

📖默默打开 svg 文档使劲翻,经过一番努力,好像有发现一个属性可以做到——<pattern> 元素。

pattern 元素在文档中是这么解析的?!

使用预定义的图形对一个对象进行填充或描边,就要用到pattern元素。pattern元素让预定义图形能够以固定间隔在x轴和y轴上重复(或平铺)从而覆盖要涂色的区域。先使用pattern元素定义图案,然后在给定的图形元素上用属性fill或属性stroke引用用来填充或描边的图案。

为了减少篇幅,就直接贴上最终代码,后面再解析。

html
<svg width="100%" height="100%" display="inline-block">
  <defs>
	<filter id="filter-img">
	  <feImage
		href="https://www.imgloc.com/images/2021/06/14/TWyQ.png"
		result="patternSource"
		x="0"
		y="0"
		width="100"
		height="100"
	  />
	  <feBlend mode="difference" in="SourceGraphic" in2="patternSource" />
	</filter>
	<pattern
	  id="img-color"
	  width="100"
	  height="100"
	  patternUnits="userSpaceOnUse"
	>
	  <rect
		width="100%"
		height="100%"
		fill-opacity=".7"
		fill="#F7A4A4"
		filter="url(#filter-img)"
	  />
	</pattern>
  </defs>
  <g
	dominant-baseline="text-after-edge"
	letter-spacing="0"
	font-family="WenYue-XinQingNianTi-NC-W8"
	font-size="60"
	font-weight="900"
  >
	<text x="10" y="70" stroke="#FFF" stroke-width=".15em" fill="#FFF">花字</text>
	<text x="10" y="70" stroke="#9C4607" stroke-width=".04em" fill="url(#img-color)">
	  花字
	</text>
  </g>
</svg>

效果图👇👇👇

svg花字

🥳Nice~

解析

  • feBlend 元素,把两个对象组合在一起,使它们受特定的混合模式控制。
    • mode 属性,设定混合模式,预设值请查看文档。
    • in 属性标识输入的原语,可以是预设值(请查看文档),也可以是 filter 元素中其他原语的 result 值。
    • in2 属性标识输入的原语,原理同上。
  • pattern 元素。
    • patternUnits 属性指示用于 <pattern> 元素几何属性的坐标系。详细可以看一下这篇文章,博主写得挺好的,传送门

pattern 元素作为容器元素,内部可以放置任意元素,案例中放置了一个 rect 矩形并填充颜色和 filter ,目的是为了颜色和滤镜图片融合在一起,然后再填充到文字上。

这里有个主要点是 pattern 元素 patternUnits 属性中使用了 userSpaceOnUse,这个在传送门解析那边说得非常详细,有兴趣的可以了解一下。

这里还使用了多一个 text 元素,主要为了多描边,这里就不再展开,详情可以看第二点。

SVG 花字绘制就讲到这里了,后期再有什么新的花字绘制再补上,你学废了吗?!🙈

Released under the MIT License.