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>
🙉🙉🙉首先先从最简单的开始,绘制一个文字,带颜色,带描边。
单描边填充花字
<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>
效果图👇👇👇(它就是第一张截图的第一个花字,因为电脑没有这个字体包,所以字体不一样)
这里就先简单解释一下属性(大神请略过)😛
首先 <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 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>
效果图👇👇👇
这里使用了一个
<g>
元素,它用于分组,它包括的多个元素为一组,可以把公用的属性放置于<g>
元素上,节省代码。
渐变花字
学了简单的填充,如果要渐变填充怎么办?
在 svg
里提供了一些渐变元素,如<linearGradient>
线性渐变, <radialGradient>
径向渐变等。
<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>
效果图👇👇👇
解析⁉️
❗注意一点:id
必须必须必须唯一,否则会出现绘制错误或者闪烁消失的错误。
svg
使用元素/滤镜主要通过 id
手段。因此需要特别注意!
defs
元素,是允许我们用来定义重复使用的图形元素,它不会呈现在界面上。linearGradient
元素,定义线性渐变。x1
、x2
、y1
、y2
用来定义线性渐变的方向,简单理解可以把它们看成两个坐标点,然后相连形成的方向就是渐变方向。<stop>
元素,用来定义一个渐变上的颜色坡度。(用于渐变元素内部)
投影花字
类似花字例子图片中的最后一个,我需要在花字后面加个阴影/投影。又该怎么做呢???
有两种方案:
- 类似多描边花字那样,使用多个花字叠加,通过修改
x
,y
来错开位置,形成投影效果。 - 使用
filter
滤镜元素。这是一个非常重要的元素,熟悉它可以做出很多漂亮的花字。🤩🤩🤩
在这里主要展示的是第二种做法;第一种方案自己可以动手练一下,或者改一改 多描边花字的参数就知道怎么做了,所以在这里就不演示了。
<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>
效果图👇👇👇
常规解析⁉️
这里实现的效果是双描边加投影,因此这里我使用了两个 text
元素叠加然后再使用一个 filter
滤镜。
在需要使用滤镜的元素上,通过 filter
属性指定滤镜元素。如 filter="url(#xxx)"
,即 使用 id
为 xxx 的滤镜。
filter
元素,作为原子滤镜操作的容器,不能直接呈现。feDropShadow
元素,用于创建输入图形的投影,只能用于filter
元素内部。dx
属性表示x
轴上的偏移。dy
属性表示y
轴上的偏移。stdDeviation
属性表示投影的模糊度。flood-color
属性表示投影颜色。flood-opacity
属性表示不透明度。
纹理花字
纹理花字其实我们并不陌生,在 office 中也有该配置🙄
本质原理就是利用一张图片当作颜色填充图形或文字。
好像 <filter>
中也有 <feImage>
把图片作为滤镜,So give it a try!
feImage
feImage
元素,把图形数据作为像素数据输出。href
属性表示对象的地址。xlink:href
也是一样效果,只不过不推荐使用了。
剩余那几个属性就不再多说了,公共属性来的。
<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>
效果图👇👇👇
🤔🤔🤔怎么好像不是我们想要的效果?分析一下代码,其实会发现这个花字是有显示的,只不过是滤镜盖住了。不难发现源头来自于 feImage
,它只是作为图像输出,并非与文字融合在一起,简单来说就是你想画一个文字,却又用一张图片覆盖在上面。
在文字不用 filter
,我直接使用 fill
呢?结果---还是不行。🤕🤕🤕
📖默默打开 svg 文档使劲翻,经过一番努力,好像有发现一个属性可以做到——<pattern>
元素。
pattern
元素在文档中是这么解析的?!使用预定义的图形对一个对象进行填充或描边,就要用到pattern元素。pattern元素让预定义图形能够以固定间隔在x轴和y轴上重复(或平铺)从而覆盖要涂色的区域。先使用pattern元素定义图案,然后在给定的图形元素上用属性fill或属性stroke引用用来填充或描边的图案。
为了减少篇幅,就直接贴上最终代码,后面再解析。
<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>
效果图👇👇👇
🥳Nice~
解析
feBlend
元素,把两个对象组合在一起,使它们受特定的混合模式控制。mode
属性,设定混合模式,预设值请查看文档。in
属性标识输入的原语,可以是预设值(请查看文档),也可以是filter
元素中其他原语的result
值。in2
属性标识输入的原语,原理同上。
pattern
元素。patternUnits
属性指示用于<pattern>
元素几何属性的坐标系。详细可以看一下这篇文章,博主写得挺好的,传送门
pattern
元素作为容器元素,内部可以放置任意元素,案例中放置了一个 rect
矩形并填充颜色和 filter
,目的是为了颜色和滤镜图片融合在一起,然后再填充到文字上。
这里有个主要点是 pattern
元素 patternUnits
属性中使用了 userSpaceOnUse
,这个在传送门解析那边说得非常详细,有兴趣的可以了解一下。
这里还使用了多一个 text
元素,主要为了多描边,这里就不再展开,详情可以看第二点。
SVG 花字绘制就讲到这里了,后期再有什么新的花字绘制再补上,你学废了吗?!🙈