手把手教你实现一个木头纹理的背景

话不多说,直接弄!

效果

实现

本次我们使用神奇的SVG来实现,还是挺简单的,这里就为大家拆分一下步骤,一步步来实现。

1. 基础画布创建

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  
</svg>

这就是最基础的一张svg画布了,我们直接设置宽高100%,让其撑满。

2. 滤镜制作

有了画布还不够,我们还需要一个盛放(展示)内容的容器以及对容器中内容的相关滤镜。

2.1 基础结构

单纯写滤镜我们无法直观看到效果,这里我们就使用rect矩形来使用滤镜。其基础结构如下:

<filter id="filter">
  // 后续滤镜内容
</filter>
<rect width="100%" height="100%" filter="url(#filter)" />

我们给滤镜写了一个id,在对应的矩形中我们应用一下即可。

2.2 噪声纹理

我们使用 feTurbulence 来生成噪声。feTurbulence 会使用柏林噪声函数生成一个程序纹理,常用于云彩、烟雾、大理石、金属等纹理的基础噪声。和PS中添加云彩效果类似。

先给出代码,然后解析:

<feTurbulence baseFrequency=".002 .02" numOctaves="9" result="n" />
  • baseFrequency=".002 .02":这是一个噪声频率,​数值越小,纹理越宽大柔和;数值越大,纹理越密集细碎。​ 这里 x 方向 0.002、y 方向 0.02,相当于竖直方向的变化更密集,容易做出类似“竖向拉丝”的感觉。

  • numOctaves="9": 表示叠加 9 个不同频率的噪声八度层,频率一层比一层高(两倍),细节越来越多。​层数越多,图案越复杂、越精细,但性能开销也更大。通常 3~6 已经足够。

  • result="n":给当前输出起个名字叫 n(noise 缩写),方便后面滤镜引用。

2.3 添加光源

<feDiffuseLighting surfaceScale="9" lighting-color="#ba8c63">
  <feDistantLight elevation="60" azimuth="-90" />
</feDiffuseLighting>

feDiffuseLighting 滤镜会把输入图像的 alpha 当作高度信息,模拟漫反射光照,生成一张光照后的颜色图,有明显的高光和阴影。 内部的 feDistantLight 则是指定光源方向。

这里对其中几个参数左下说明:

  • surfaceScale="9":控制“高度起伏”的强度,可以理解为凹凸有多深。数值越大,明暗对比越强,越有金属 / 皮革的起伏感。​

  • lighting-color="#ba8c63":光的颜色,因为我们要木材纹理,因此这里是棕金色,更贴近木头的颜色。

  • elevation="60":光照的高度角(0° 在地平线,90° 直射),60° 是比较高的斜上方光源。​

  • azimuth="-90":光源方位角,单位是度。这里从左侧照向右侧,从而产生从左到右的光感。

2.4 添加扭曲

到上一步其实材质效果已经出来了,但是还缺乏类似年轮的扭曲效果,因此为了更真那么一点点,就增加一个扭曲滤镜来优化一下。

<feDisplacementMap in2="n" scale="50" />

feDisplacementMap 会使用第二个输入(in2 )的颜色通道作为位移向量,把第一个输入(in )的像素往各个方向挪动,从而产生类似水波、玻璃扭曲、抖动等效果。这个滤镜非常常见,以后也会分享一些相关的效果。

  • in2="n":位移图使用第一步 feTurbulence 生成的噪声 n。​
  • scale="50":位移强度,数值越大,扭曲越严重。

到这里就是我们上面效果图的样式。

拓展点

1. 噪声的可选属性

在我们上述的噪声纹理中,其实还可以增加一些属性来进行更多的控制。例如 typeseed

  • type:控制噪声的类型,更躁动还是更柔和,有两个值
    • turbulence:更激烈的噪声,明暗对比明显。
    • fractalNoise:更柔和连续,适合云雾、柔和纹理。​
  • seed:随机种子,相同 seed 会生成同样的噪声,不同 seed 会产生不同纹理。​

例如,我们可以将噪声改为更柔和的样式

<feTurbulence type="fractalNoise" baseFrequency=".002 .02" numOctaves="9" seed="2" result="n" />

2. 光源的输入与输出

案例中 feDiffuseLighting 没有显式写 in="n",浏览器会把它的输入默认为前一个滤镜输出(即上面的 feTurbulence)。

​输出结果默认会用一个自动生成的名字(如果不指定 result),这里没有继续显式引用,就直接被下一个滤镜作为链式输入(SVG 会按顺序串联)。

完整写法为

<feDiffuseLighting in="n" result="light" surfaceScale="9" lighting-color="#ba8c63">
  <feDistantLight elevation="60" azimuth="-90" />
</feDiffuseLighting>

3. 扭曲滤镜的第一输入与通道控制

在我们给的例子中,最后的扭曲滤镜 feDisplacementMap 只有 in2 而未写 in ,默认把上一步 feDiffuseLighting 的输出作为主图像输入。

在完整写法之中,也会有指定通道选择,例如 xChannelSelector="R" / yChannelSelector="G":指定使用位移图的红色通道控制 x 方向位移,绿色通道控制 y 方向位移。

我们省略了 xChannelSelectoryChannelSelector ,会使用默认通道,但大部分简单场景效果仍然可用的。


<svg xmlns="http://www.w3.org/2000/svg">
  <filter id="filter">
    <feTurbulence baseFrequency=".002 .02" numOctaves="9" result="n" />
    <feDiffuseLighting surfaceScale="9" lighting-color="#ba8c63">
      <feDistantLight elevation="60" azimuth="-90" />
    </feDiffuseLighting>
    <feDisplacementMap in2="n" scale="50" />
  </filter>
  <rect width="100%" height="100%" filter="url(#filter)" />
</svg>

参考资料:


你可以在这里找到大鹅所有CSS知识分享哦
:red_triangle_pointed_down::red_triangle_pointed_down::red_triangle_pointed_down::red_triangle_pointed_down::red_triangle_pointed_down:
:fire:【冷门知识】鹅のCSS大合集!长期追更~ 收藏 ≈ 学会

60 个赞

点点赞吧,已经在肝元旦的教程了。生产队的驴都没我勤奋 :tieba_087:

6 个赞

鹅佬 威武

3 个赞

大鹅佬回归本行了 :joy:

4 个赞

感谢佬友分享~

3 个赞

生产队的骡子呢?

4 个赞

骡子被吃了

3 个赞

不错啊,大鹅

2 个赞

mark

3 个赞

一直老本行,只不过看的佬少 :tieba_087:

3 个赞

骡子不是很难吃的吗???

2 个赞

学习一下,感谢大佬

2 个赞

你也不错,点赞了吗

1 个赞

收藏等于我会了

2 个赞

一把孜然一把胡椒,还能有多难吃

1 个赞

我是废物:来个提示词

2 个赞

[!info]感谢分享 大鹅佬辛苦了~

2 个赞

不是css教程我还不习惯

2 个赞

佬太有实力了

2 个赞

感谢分享

2 个赞