前端页面实现figma的noise效果

前端页面实现figma的noise效果

Image.png

某日想要在页面上显示一个噪点效果的设计,在figma里面用到上次更新新出的功能effects的noise,某刻脑子执念不想导出图片,直接用代码撸的想法。

噔噔噔噔~ svg滤镜之feTurbulence闪亮登场。

feTurbulence

feTurbulence 是 SVG中一个非常强大滤镜效果,基于 Perlin 噪声的图像纹理处理。它可以模拟自然界中的各种复杂纹理效果,比如云朵、火焰、烟雾、大理石纹理等,常用于为图形添加自然的随机纹理或做图像扭曲变形的基础。

假想一下,你用笔在纸上画云朵或大理石的花纹,这些纹理看起来杂乱无章(先确定我能画得出来),但其实是有一定规律的随机变化。feTurbulence 就是通过数学上的“噪声函数”(Perlin 噪声)来自动生成这种复杂的纹理图案。它不像普通的滤镜那样对已有图像做模糊或颜色变化,而是直接生成一张“噪声图”,这张图可以用来做各种效果,比如:

  • 作为纹理覆盖在图形上,模拟自然纹理;
  • 结合其他滤镜(如 feDisplacementMap)实现图像扭曲、液化效果;
  • 动态改变参数实现动画效果,比如云彩飘动、火焰跳动等。

滤镜的属性和含义

feTurbulence滤镜主要有5个属性,这些属性共同决定了生成噪声的样式、细节和形态:

AI搜出来的数据,给出的区间数据不要太信

属性名作用说明取值及默认值
type噪声类型,决定生成的是“湍流”还是“分形噪声”"turbulence"(默认,纹理更“条纹状”)或 "fractalNoise"(更“云雾状”)
baseFrequency基础频率,控制噪声的大小和密度,数值越小噪声图形越大,越大则噪声越细密单个值或两个值(x轴和y轴频率),通常0.02~0.2之间
numOctaves倍频数量,决定噪声的细节层次,数值越大细节越丰富,但计算量也越大整数,默认1,通常1~5之间,超过一定值后视觉变化不明显
seed伪随机数生成的起始值,影响噪声图形的具体形状和位置,但不改变频率和密度整数,默认0
stitchTiles是否启用无缝拼接,影响噪声在边界处的平滑连接"noStitch"(默认,不平滑)或 "stitch"(平滑无缝拼接)

1. type属性

  • turbulence:产生带有条纹感的湍流噪声,纹理看起来更“线性”和“拉丝”。
  • fractalNoise:产生更均匀、云雾状的分形噪声,纹理更柔和、自然,常用于云朵、烟雾模拟。

Image.png

2. baseFrequency属性

控制噪声的“频率”,也就是纹理的大小和密度。数值越小,噪声纹理越大块,越粗糙;数值越大,纹理越细腻、密集。它可以接受一个值(x和y轴相同)或两个值(分别控制x轴和y轴的频率),这样可以生成拉伸变形的噪声效果。

Image.png

Image.png

3. numOctaves属性

“倍频”数量,类似于在不同频率上叠加多个噪声层,使得纹理更丰富和自然。数值越大,细节越多,但性能开销也越大。通常1~5之间即可满足大多数需求。

Image.png

4. seed属性

伪随机种子,改变它会生成不同的噪声形状,但不会改变噪声的频率和密度。可以用来生成多种不同样式的纹理。

通俗的讲,就是你抓了一定数量的蚂蚁,放在一个固定尺寸的盒子里,你同一个时间不同相机拍摄的照片里面蚂蚁方向是一致的,不同时间的就不一样的,把这个东西叫做纹理。直观体现就是把相同seed和不同seed的连接在一起,相同数值的seed连接处是纹理贴合的,不同的seed的明显的错位感。

Image.png

5. stitchTiles属性

决定噪声图形在边界处是否无缝拼接。默认是noStitch,多个元素使用时边界处纹理不连续;设置为stitch时,边界处纹理平滑连续,适合做平铺纹理。

说是这么说,但是我再怎么调试,目测也没有感觉到不一样的区别,不确定是不是我手法的问题。

下图为四个拼接

Image.png

三、SVG实例

纸上来得终觉浅,撸实例看效果

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <filter id="noise1">
    <feTurbulence baseFrequency="1" numOctaves="10" seed="10"/>
  </filter>
  <rect height="200" width="200" filter="url(#noise1)" />
</svg>

相应的我得到了这张图

Image.png

操作过程中,有过想法将SVG代码和浏览器的展示效果,一同放在figma里面并排进行展示,当我复制上面的svg代码,在fgima没有点击文字工作的时候,它自动识别为了svg图片贴在画版上,也正确的显示出了正方形,但是燥音的效果完全没有,重新从figma里面把该元素的svg复制出来,noise相关的代码信息还在。

增加上颜色填充

添加上一个颜色,不要忘记加feBlend把噪音和颜色图形合成,不然无法看到颜色,还是只能看到颜色被噪音覆盖的噪音图层。

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
      <filter id="noise11">
        <feTurbulence baseFrequency="1" numOctaves="10" seed="10" result="noise"/>
        <feBlend in="SourceGraphic" in2="noise" mode="multiply"/>
      </filter>
      <rect height="200" width="200" fill="red" filter="url(#noise11)" />
    </svg>

Image.png

当然还可以增加上渐变,动画等等,大家自行试验。

AnimatedImage.gif

文字

当然或者跟文字组成这样的效果,配合 feDisplacementMap

<svg width="600" height="200" xmlns="http://www.w3.org/2000/svg">
      <filter id="noise88">
        <feTurbulence type="fractalNoise" baseFrequency="0.04" numOctaves="1" result="noise"/>
        <feDisplacementMap in="SourceGraphic" in2="noise" scale="50" />
      </filter>
      <text x="10" y="100" font-size="80" filter="url(#noise88)">秋野的意外</text>
    </svg>

Image.png

图片

<svg width="320" height="180" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <filter id="turbulence1">
          <feTurbulence baseFrequency="1" numOctaves="1" seed="10" result="turbulence"/>
          <feImage xlink:href="/zhenyu-luo--BC5jQsbJss-unsplash.jpg"
                   x="0" y="0" width="320" height="180" result="image"/>
          <feComposite in="turbulence" in2="image" operator="over" result="composite"/>
        </filter>
      </defs>
      <rect width="320" height="180" filter="url(#turbulence1)" />
    </svg>

Image.png

或者把刚刚上面的扭曲文字的方法,再叠加上图片,做成水面荡漾的效果。

<svg viewBox="0 0 180 100">
      <filter id='noise' x='0%' y='0%' width='100%' height='100%'>
        <feTurbulence baseFrequency="0.01 0.4" result="NOISE" numOctaves="2"/>
        <feDisplacementMap in="SourceGraphic" in2="NOISE" scale="20" xChannelSelector="R" yChannelSelector="R"></feDisplacementMap>
      </filter>
      <image xlink:href="/zhenyu-luo--BC5jQsbJss-unsplash.jpg" x="0" y="0" width="100%" height="100%" filter="url(#noise)"></image>
      <text dx="10" dy="50" font-size="30px" font-weight="bold" filter="url(#noise)">WATER</text>
    </svg>

Image.png

所以跟我的世界里面的世界一样,方块是里面的,具体玩出怎么样的效果,还看各位自己玩的彦祖。

四、与CSS其它结合

有的筒子这时候冒出来说,SVG当然强了,我要用CSS实现呢

当然了,噪点这张图片还是需要SVG的,只是把原来SVG里面的属性用CSS的来代替。

实现思路:噪点SVG图片当css里面的背景使用,SVG直接复制到css的background无法使用,需要进行转换:

一种是转换为base64的,坏处了看起来不直观,要调整还得重新倒腾

一种是将SVG的代码压缩成一行,把特殊字符进行转换,如#,<,>等。这样的代码比较直接

或者直接把SVG保存为文件

现在来同样实现上面的渐变颗粒效果,纯色了就不试了。

// html 空div 
<div class="box">
</div>

// css 部分
.box{
  height: 200px;
  width: 200px;
  background-image:linear-gradient(to right,rgba(255,0,0,0),rgba(255,0,0,1)), url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><filter id="noise1"><feTurbulence baseFrequency="1" numOctaves="10" seed="10"/></filter><rect width="200" height="200" fill="%23ccc" filter="url(%23noise1)"/></svg>');
}

Image.png

目测没有什么差距

好像不太好看啊,加花点,复制点云彩般的渐变加点噪点试试。

<div class="box-color2"></div>


.box-color2{
    height: 200px;
    width: 200px;
    background:
        radial-gradient(at 40% 20%, hsla(28,100%,74%,1) 0px, transparent 50%),
        radial-gradient(at 80% 0%, hsla(189,100%,56%,1) 0px, transparent 50%),
        radial-gradient(at 0% 50%, hsla(355,100%,93%,1) 0px, transparent 50%),
        radial-gradient(at 80% 50%, hsla(340,100%,76%,1) 0px, transparent 50%),
        radial-gradient(at 0% 100%, hsla(22,100%,77%,1) 0px, transparent 50%),
        radial-gradient(at 80% 100%, hsla(242,100%,70%,1) 0px, transparent 50%),
        radial-gradient(at 0% 0%, hsla(343,100%,76%,1) 0px, transparent 50%),url("data:image/svg+xml;charset=UTF-8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='200'%20height='200'%3E%3Cfilter%20id='noise'%3E%3CfeTurbulence%20baseFrequency='1'%20numOctaves='1'%20seed='10'/%3E%3C/filter%3E%3Crect%20width='200'%20height='200'%20filter='url(%23noise)'/%3E%3C/svg%3E");
  }

Image.png

处理图片效果的话,直接把噪点SVG叠加在图片之上就行。

Image.png

最后

没有什么动画的需求或者特别的执念的话,还是直接导出图片直接引用吧,太倒腾了。