想要彻底理解和使用该滤镜还是需要好好研究一下的,但是如果真正理解和会使用这个滤镜,那么就可以生成一些例如云彩,火焰,大理石纹理,等绚烂图案。本篇文章我们一起研究一下这个滤镜,在文章的后面再分享一些该滤镜的特效源码。
滤镜原理和语法
噪声来源于计算机图形学,例如我们在游戏中使用的火焰效果,就是基于噪声函数实现的。现实中常见的噪声就是电视没有台的时候出现的“雪花点“。在计算机图像学中常见的噪声有6种,这里面就包含svg使用的噪声:Perlin噪声。
关于该噪声的原理稍微研究了一下:可以理解为随机点的曲线差值。对于一维的效果如下:
对于随机生成的点,用曲线进行差值。对于二维的,可以理解成在一维基础上的扩展。(毕竟我们不是做计算机图形学的,不必研究的很清楚,大概懂得原理就行了)我们知道了这个滤镜的大概原理和作用,那就介绍一下这个滤镜的语法。
feTurbulence滤镜有5个属性:
- baseFrequency(默认值:0 0)可以接受两个参数噪声频率,值越大,噪声点越小,越密集
- numOctaves(默认值:1)这是噪声叠加,能使噪声细节更加丰富
- seed (默认值:0)随机值的入参
- stitchTiles(默认值:noStitch)
- type (默认值:turbulence)或者fractalNoise,后者更为平滑。
只看语法是效果不大的,毕竟纸上得来空觉浅吗。下面我们对各个属性都分别测验一下。
看如下代码:
<svg width="500" height="500" viewBox="0 0 500 500">
<defs>
<filter id="turbu_filter">
<feTurbulence type="turbulence"
baseFrequency="0 0"
numOctaves="1"
stitchTiles="noStitch"
seed="3" >
<animate attributeName="baseFrequency" attributeType="XML" from="0 0" to="1 1" dur="6s" repeatCount="indefinite" />
</feTurbulence>
</filter>
</defs>
<rect x="0" y="0" width="300" height="200" style="filter:url(#turbu_filter);" />
</svg>
这是噪声频率(baseFrequency)从0到1的变化,效果图如下:
numOctaves,噪声叠加就是在噪声的边缘进行叠加。值越大叠加的效果也不明显。看代码:
<svg width="500" height="500" viewBox="0 0 500 500">
<defs>
<filter id="turbu_filter1">
<feTurbulence type="turbulence"
baseFrequency="0.1 0.1"
numOctaves="1"
stitchTiles="noStitch"
seed="3" >
<animate attributeName="numOctaves" attributeType="XML" keyTimes="0; 0.2; 0.4; 0.6; 0.8; 1" values="1;2;3;4;5;6;" begin="0s" dur="3s" repeatCount="indefinite" />
</feTurbulence>
</filter>
</defs>
<rect x="0" y="0" width="300" height="200" style="filter:url(#turbu_filter1);" />
</svg>
效果如下:
当叠加的值大于3的时候图像变化已经不明显了。
seed是随机数输入值,这个变化并不是连续的。看如下代码:
<svg width="500" height="500" viewBox="0 0 500 500">
<defs>
<filter id="turbu_filter3">
<feTurbulence type="turbulence"
baseFrequency="0.2 0.2"
numOctaves="1"
stitchTiles="noStitch"
seed="1" >
<animate attributeName="seed" attributeType="XML" from="1" to="10" dur="6s" repeatCount="indefinite" />
</feTurbulence>
</filter>
</defs>
<rect x="0" y="0" width="300" height="200" style="filter:url(#turbu_filter3);" />
</svg>
效果如下:
另外两个就不做单独的介绍了。我感觉可以看一w3c的例子还是比较经典的:
下面介绍几个经典的案例:
噪声滤镜实例
蓝天白云效果
先看效果:
我老婆说了感觉哪里不对,不像是白云,说明还是有需要改进的地方。想法是通过噪声点对椭圆的白云进行像素偏移,再给椭圆增加动画就行了。源码如下:
<svg width="1500" height="500" viewBox="0 0 1500 500" style="background-color: blue;">
<defs>
<filter id="turbu_filter333">
<feTurbulence
result="tirld"
type="turbulence"
baseFrequency="0.005"
numOctaves="3"
stitchTiles="noStitch"
seed="0" >
</feTurbulence>
<feDisplacementMap in="SourceGraphic" in2="tirld" scale="100" xChannelSelector="B" yChannelSelector="R"></feDisplacementMap>
</filter>
<radialGradient id="radia_gra" cx="50%" cy="20%" r="50%" fx="50%" fy="50%">
<stop offset="0%" stop-color="rgba(255,255,255,1)"></stop>
<stop offset="70%" stop-color="rgba(255,255,255,0.8)"></stop>
<stop offset="100%" stop-color="rgba(255,255,255,0)"></stop>
</radialGradient>
</defs>
<!-- <rect x="0" y="0" width="100%" height="100%" style="fill:url(#radia_gra);filter:url(#turbu_filter333);"/> -->
<g x="0" y="0" width="100%" height="100%" style="filter:url(#turbu_filter333);">
<ellipse cx="300" cy="200" rx="150" ry="50" fill="url(#radia_gra)">
<animate attributeName="cx" id="an1" from="300" to="100" begin="0s;an2.end" dur="3s" />
<animate attributeName="cx" id="an2" from="100" to="300" begin="an1.end" dur="3s"/>
<animate attributeName="cy" id="an3" from="200" to="0" begin="0s;an4.end" dur="3s"/>
<animate attributeName="cy" id="an4" from="0" to="200" begin="an3.end" dur="3s"/>
</ellipse>
<ellipse cx="-300" cy="400" rx="550" ry="150" fill="url(#radia_gra)">
<animate attributeName="cx" from="-300" to="1600" begin="0s" dur="15s" repeatCount="indefinite"/>
</ellipse>
</g>
</svg>
大家可以在我做的基础上进行改进,欢迎大家留言。
褶皱纸张效果
效果如下:
截图出来后效果不太明显。大家可以看源码在本地尝试:
<svg width="1500" height="500" viewBox="0 0 1500 500">
<defs>
<filter id="turbu_filter">
<feTurbulence
result="tirld"
type="turbulence"
baseFrequency="0.1"
numOctaves="2"
stitchTiles="noStitch"
seed="1" >
</feTurbulence>
<feSpecularLighting
in="tirld"
lighting-color="#f2fde2"
surfaceScale="5"
specularConstant="1"
specularExponent="2"
result="fe_ligt"
>
<feDistantLight azimuth="45" elevation="15"/>
</feSpecularLighting>
</filter>
</defs>
<rect x="0" y="0" width="100%" height="100%" style="filter:url(#turbu_filter);"/>
</svg>
就是在波纹上增加白色的光照,将文字写到纸张上能增加年代感。特别是艺术字的话。
水波纹效果
这种效果是最常见的滤镜应用,网上资源比较多,并且在现实项目中很少能用得到。看一下我这实现的效果,实际上需要两张图片,一张是原图片,一张是水的图片放到原图片上,加上滤镜效果。
我的截图有点随意,做出的效果有瑕疵。大家知道原理可以自行优化。
主要代码如下:
<svg width="500" height="300">
<defs>
<filter id="filter-ripple">
<feTurbulence id="smoke_turbulence" result="smoke" type="fractalNoise" baseFrequency=".03" numOctaves="2" />
<feDisplacementMap in="SourceGraphic" in2="smoke" scale="20" xChannelSelector="B" yChannelSelector="R"/>
</filter>
</defs>
<image xlink:href="../img/fj.png" x="0" y="0" width="500" height="300"></image>
<image xlink:href="../img/shuibo.png" x="0" y="200" width="500" height="100" style="filter:url(#filter-ripple)"></image>
</svg>
为噪声滤镜添加动画就可以了。
烟雾文字
如图所示:
该效果需要借助css和js帮忙。首先是通过css做出渐变字体,然后用js修改噪音大小。渐变字体用到css3的-webkit-background-clip:text。接下来就没什么难的了。
结束语
svg噪声滤镜是个神奇的滤镜,可以制造出很多绚烂的效果。上面简单的例子只是抛砖引玉。
行文到此,基本所有的svg滤镜已经介绍完了。关于svg的dom操作不再介绍,项目中很少用到。谢谢观赏。