前端页面实现figma的noise效果
某日想要在页面上显示一个噪点效果的设计,在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:产生更均匀、云雾状的分形噪声,纹理更柔和、自然,常用于云朵、烟雾模拟。
2. baseFrequency属性
控制噪声的“频率”,也就是纹理的大小和密度。数值越小,噪声纹理越大块,越粗糙;数值越大,纹理越细腻、密集。它可以接受一个值(x和y轴相同)或两个值(分别控制x轴和y轴的频率),这样可以生成拉伸变形的噪声效果。
3. numOctaves属性
“倍频”数量,类似于在不同频率上叠加多个噪声层,使得纹理更丰富和自然。数值越大,细节越多,但性能开销也越大。通常1~5之间即可满足大多数需求。
4. seed属性
伪随机种子,改变它会生成不同的噪声形状,但不会改变噪声的频率和密度。可以用来生成多种不同样式的纹理。
通俗的讲,就是你抓了一定数量的蚂蚁,放在一个固定尺寸的盒子里,你同一个时间不同相机拍摄的照片里面蚂蚁方向是一致的,不同时间的就不一样的,把这个东西叫做纹理。直观体现就是把相同seed和不同seed的连接在一起,相同数值的seed连接处是纹理贴合的,不同的seed的明显的错位感。
5. stitchTiles属性
决定噪声图形在边界处是否无缝拼接。默认是noStitch,多个元素使用时边界处纹理不连续;设置为stitch时,边界处纹理平滑连续,适合做平铺纹理。
说是这么说,但是我再怎么调试,目测也没有感觉到不一样的区别,不确定是不是我手法的问题。
下图为四个拼接
三、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>
相应的我得到了这张图
操作过程中,有过想法将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>
当然还可以增加上渐变,动画等等,大家自行试验。
文字
当然或者跟文字组成这样的效果,配合 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>
图片
<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>
或者把刚刚上面的扭曲文字的方法,再叠加上图片,做成水面荡漾的效果。
<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>
所以跟我的世界里面的世界一样,方块是里面的,具体玩出怎么样的效果,还看各位自己玩的彦祖。
四、与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>');
}
目测没有什么差距
好像不太好看啊,加花点,复制点云彩般的渐变加点噪点试试。
<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");
}
处理图片效果的话,直接把噪点SVG叠加在图片之上就行。
最后
没有什么动画的需求或者特别的执念的话,还是直接导出图片直接引用吧,太倒腾了。