我们前面讲述的svg的各种滤镜,有图像模糊,添加阴影,修改图像颜色,增加光照,图像合成叠加滤镜。前面的滤镜均不会改变像素自身的位置。feDisplacementMap滤镜是修改像素的位置。常见的应用是为元素添加水波为效果。这篇文章通过一步一步带大家通过实现水波纹效果,来认识这个滤镜。先上效果:
下面来讲一下具体的实现。feDisplacementMap滤镜是使用一个输入源的颜色值,对另外一个输入源的元素位置进行像素平移。feDisplacementMap滤镜的语法:
scale:平移比例比例越大,平移距离就越大。
in:需要改变元素位置的输入源。
in2:使用该输入的颜色值改变in输入的位置。
xChannelSelector:x轴的使用的偏移颜色可取值R,G,B,A。
yChannelSelector:y轴的使用的偏移颜色可取值R,G,B,A。
俗话说纸上得来空觉浅,绝知此事要躬行,下面我们通过实例来一起研究一下这个属性。
下面我们使用:
这个图片对我们的风景图片:
测试该滤镜,代码如下:
<svg width="500" height="300">
<defs>
<filter id="filter-ripple">
<feImage result="pict2" xlink:href="../img/water.png" ></feImage>
<feDisplacementMap
scale="20"
color-interpolation-filters="sRGB"
xChannelSelector="R"
yChannelSelector="R"
in="SourceGraphic"
in2="pict2">
</feDisplacementMap>
</filter>
</defs>
<image xlink:href="../img/fj.png" x="0" y="0" width="500" height="300" style="filter:url(#filter-ripple)"></image>
</svg>
效果如图:
如果我们将scale修改为10效果如下:
可能有好奇的同学确实对具体的偏移逻辑感兴趣,通过查看mdn知道偏移公式如下:
P'(x,y) ← P( x + scale * (XC(x,y) - 0.5), y + scale * (YC(x,y) - 0.5))
在实际使用过程中不用知道太详细,我们到能根据颜色值对图像偏移,并且能控制偏移比例就行了。
到这里我们发现,我们要做的是水波纹的扩散效果。这个滤镜对整个图片做了处理,我们怎么能处理图片的一部分呢?当然我们首先想到的是改变in2输入源的大小,代码如下:
<svg width="500" height="300">
<defs>
<filter id="filter-ripple">
<feImage result="pict2" xlink:href="../img/water.png" x="0" y="0" width="200" height="120"></feImage>
<feDisplacementMap
scale="10"
color-interpolation-filters="sRGB"
xChannelSelector="R"
yChannelSelector="R"
in="SourceGraphic"
in2="pict2">
</feDisplacementMap>
</filter>
</defs>
<image xlink:href="../img/fj.png" x="0" y="0" width="500" height="300" style="filter:url(#filter-ripple)"></image>
</svg>
这样能不能满足我们的需求呢?看下效果:
我们看到这并不是我们想要的效果,只把滤镜处理的一部分显示出来了。图片剩余的部分并未显示。那接下来怎么做呢?这时候有的同学就想起了我们上一篇文章讲的两个滤镜:feblend和feComposite,具体该使用哪一个呢?可以看到们的这个效果明显有一个阴影,并且随着位置改变阴影会变化:例如:
<svg width="500" height="300">
<defs>
<filter id="filter-ripple">
<feImage result="pict2" xlink:href="../img/water.png" x="50" y="50" width="200" height="120"></feImage>
<feDisplacementMap
result="partImg"
scale="20"
color-interpolation-filters="sRGB"
xChannelSelector="R"
yChannelSelector="R"
in="SourceGraphic"
in2="pict2">
</feDisplacementMap>
</filter>
</defs>
<image xlink:href="../img/fj.png" x="0" y="0" width="500" height="300" style="filter:url(#filter-ripple)"></image>
</svg>
就变成了下面的样子:
至于为什么会出现这样的阴影背景,我也不知道,可能是svg本身就是这么设计的。所以现在我们需要一个滤镜将这个效果裁剪一下,正好用到了我们上一节讲的滤镜:feComposite,我们可以使用波纹图片最输入源将这个结果裁剪,去掉后面的背景:代码如下:
<svg width="500" height="300">
<defs>
<filter id="filter-ripple">
<feImage result="pict2" xlink:href="../img/water.png" x="50" y="50" width="200" height="120"></feImage>
<feDisplacementMap
result="partImg"
scale="20"
color-interpolation-filters="sRGB"
xChannelSelector="R"
yChannelSelector="R"
in="SourceGraphic"
in2="pict2">
</feDisplacementMap>
<feComposite in="partImg" in2="pict2" operator="in"/>
</filter>
</defs>
<image xlink:href="../img/fj.png" x="0" y="0" width="500" height="300" style="filter:url(#filter-ripple)"></image>
</svg>
效果如图:
这就达到我们想要的效果了,然后我们可以将这个滤镜效果叠加到原图片上,就可以做出部分水波纹效果,代码如下:
<svg width="500" height="300">
<defs>
<filter id="filter-ripple">
<feImage result="pict2" xlink:href="../img/water.png" x="50" y="50" width="200" height="120"></feImage>
<feDisplacementMap
result="partImg"
scale="40"
color-interpolation-filters="sRGB"
xChannelSelector="R"
yChannelSelector="R"
in="SourceGraphic"
in2="pict2">
</feDisplacementMap>
<feComposite result="resutPart" in="partImg" in2="pict2" operator="in"/>
<feComposite in="resutPart" in2="SourceGraphic" operator="over"/>
</filter>
</defs>
<image xlink:href="../img/fj.png" x="0" y="0" width="500" height="300" style="filter:url(#filter-ripple)"></image>
</svg>
但是仔细看会发现贴图的位置不对,向上发生了偏移。经过测试发现:图片偏移的位置和feDisplacementMap滤镜的sacle成正比,也就是scale值越大偏移距离越大。有兴趣的同学可以调试一下。所以我们做水波纹效果的时候,可以将动画效果由大变小,最后变为0。并且在动画过程中人眼很难捕捉到这些细小的差异,就能实现一个冒牌的水波纹动画效果。当然这个水波纹效果是有矩形边界的的,换一个波纹图片就好了。大家可以根据需要自行制作。
有了上面的效果我们下面就可以制作动画了。具体的代码这里就不写了。大家可以查看源码:水波纹动画效果。当然这个神奇的滤镜还有很多用途等待大家开发,我这里抛砖引玉,谢谢大家观看。下一节我们介绍svg的最后一滤镜。feTurbulence。看看他能造出来那些神奇的效果。
暂无评论内容