巧用 SVG 滤镜还能制作表情包?

简介: 巧用 SVG 滤镜还能制作表情包?

背景



今天在群里面聊天,看到有人发这个表情包:

45f2b3944fbe4679a3645fdc679fd439_tplv-k3u1fbpfcp-zoom-1.gif


刚好最近一直在学习 SVG,脑海中就把这个表情包的效果和 feTurbulence 滤镜关联了起来。


如果我们有一张类似上图表情包的静态图,利用 feTurbulence 生成的噪声函数,运用在静态的表情包之上,再添加些许动画,是不是也能制作一张类似的动图效果呢?


什么是 SVG feTurbulence 滤镜?



如果你对 SVG 滤镜还不算太了解,可以简单看看我的这篇文章入门:有意思!强大的 SVG 滤镜


这里我们会用到 SVG 中的 feTurbulence 滤镜。再简单介绍下。


feTurbulence 滤镜


turbulence 意为湍流,不稳定气流,而 SVG <feTurbulence> 滤镜能够实现半透明的烟熏或波状图像。通常用于实现一些特殊的纹理。滤镜利用 Perlin 噪声函数创建了一个图像。噪声在模拟云雾效果时非常有用,能产生非常复杂的质感,利用它可以实现了人造纹理比如说云纹、大理石纹的合成。


简单看个 DEMO:


<div>Coco</div>
<div class="turbulence">Coco</div>
<svg>
    <filter id="fractal" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
        <feTurbulence id="turbulence" type="fractalNoise" baseFrequency="0.03" numOctaves="1" />
        <feDisplacementMap in="SourceGraphic" scale="50"></feDisplacementMap>
    </filter>
</svg>


.turbulence {
    filter: url(#fractal);
}


左边是正常的效果,后边是应用了 <feTurbulence> 的效果,你可以试着点进 Demo,更改 baseFrequency 和 numOctaves 参数的大小,可以看到不同的效果:

6be030b70eae40f99188ed38dc605d95_tplv-k3u1fbpfcp-zoom-1.png


CodePen Demo -- feTurbulence text demo


将 feTurbulence 滤镜应用于图片


我们尝试把上述 DEMO 中的文字转换成图片。我找到了一张静态的哭的表情包:

71e8eea4416c46b4ad1ff566f6247368_tplv-k3u1fbpfcp-zoom-1.png



简单改造下代码:


<div></div>
<svg>
    <filter id="fractal" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
        <feTurbulence id="turbulence" type="fractalNoise" baseFrequency="0.09" numOctaves="1" ></feTurbulence>
        <feDisplacementMap in="SourceGraphic" scale="15"></feDisplacementMap>
    </filter>
</svg>
div {
    background: url(image.jpg);
    filter: url(#fractal);
}


效果如下:

e514364c60914cdfb8b99a4139b39262_tplv-k3u1fbpfcp-zoom-1.png


有点那个意思了,我们通过 feTurbulence 滤镜得到了噪声图形,然后通过 feDisplacementMap 滤镜根据 feTurbulence 所产生的噪声图形进行形变,扭曲,液化,得到最终的效果。


通过调整 feTurbulence 中的 baseFrequency 和 numOctaves 以及 feDisplacementMap 中的 scale 参数,我们可以调试得到不同的效果。


接下来,我们再给上述滤镜添加一个动画,利用 SVG 的 animate 标签,动态的改变 baseFrequency参数:


<svg>
    <filter id="fractal" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
        <feTurbulence id="turbulence" type="fractalNoise" baseFrequency="0.1 0.1" numOctaves="1" >
            <animate
                    attributeName="baseFrequency"
                    from="0.1 0.1"
                    to="0.08 0.01"
                    dur="3.5s"
                    repeatCount="indefinite"/>
        </feTurbulence>
        <feDisplacementMap in="SourceGraphic" scale="15"></feDisplacementMap>
    </filter>
</svg>


添加了动画之后,同样作用于图片之上,我们就可以得到如下的效果:


d6cd23d965a442b78625e0521d4132d4_tplv-k3u1fbpfcp-watermark.gif


由于截图软件的帧率问题,看着有点慢,你可以戳进 DEMO 看看实际效果,还是挺有意思的,至此我们就简单的利用 CSS 配合 SVG 的方式,通过一张静态图得到了一个动态的表情包啦。😁


CodePen Demo -- 使用 SVG 滤镜 feTurbulence 让图片动起来


巧用 feTurbulence 滤镜实现各种动效



嘿,feTurbulence 当然不是仅能实现这个而已,下面我们再探索一些有意思的场景。

首先,再明确下我们主要使用到的两个滤镜 feTurbulence 和 feDisplacementMap,它们的核心代码:


<svg>
    <filter id="feDisplacementMap" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="64">
        <feTurbulence type="fractalNoise" baseFrequency="0.0995" numOctaves="1" result="img" />
        <feDisplacementMap id="feDis" in="SourceGraphic" in2="img" scale="600" />
    </filter>
</svg>


其中滤镜中的几个参数 -- baseFrequency、numOctaves、scale 的改变其实都会得到不一样的效果。我们动态的变化其中的一个或多个也都可以得到不同的动画效果。


动态改变 feDisplacementMap 的 scale 的参数


feDisplacementMap 滤镜是用于改变元素和图形的像素位置的。该滤镜通过遍历原图形的所有像素点,通过 feTurbulence 滤镜产生的噪声函数将原图像的每个像素点重新映射到一个新的位置,形成一个新的图形。


而 scale 表示新得到的图像的扭曲程度,这个值越大,图像越加扭曲不可识别。

通过设置一个非常大初始值,我们可以完全将输入的任何源图像粒子化,看看这个 Demo:


<div></div>
<div class="fractal"></div>
<svg viewBox="0 0 200 200" width="200px" height="200px">
    <defs>
        <filter id="fractal" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="200">
            <feTurbulence type="fractalNoise" baseFrequency="0.995" numOctaves="10" seed="1" stitchTiles="noStitch" result="img" />
            <feDisplacementMap in="SourceGraphic" in2="img" xChannelSelector="R" yChannelSelector="G" scale="600" />
        </filter>
    </defs>
</svg>
div {
    width: 200px;
    height: 200px;
    background: url(image.jpeg)
}
.fractal {
    filter: url(#fractal);
}


左边为正常的图像,右边为作用了设置了 SVG 滤镜效果的图像,并且设置了 scale="600",完全将图片粒子化了:

e5efcbcd05804d19bcc387eda38ce074_tplv-k3u1fbpfcp-zoom-1.png



这个时候,让滤镜的 scale="600" 动态变化回 scale="1"(当此参数为 1 时,图像表示为正常状态),也就能实现一个图形从粒子化到正常化的转变:


<svg viewBox="0 0 200 200" width="200px" height="200px">
    <filter id="fractal" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="200">
        <feTurbulence type="fractalNoise" baseFrequency="0.995" numOctaves="10" seed="1" result="img" />
        <feDisplacementMap in="SourceGraphic" in2="img" xChannelSelector="R" yChannelSelector="G" scale="600">
            <animate attributeName="scale" values="600;0;0" keyTimes="0;0.75;1" begin="0s" dur="2s" repeatCount="indefinite" />
        </feDisplacementMap>
    </filter>
</svg>


效果如下:


bad9a4b1e40c4f51a54dc2f28d84e2e5_tplv-k3u1fbpfcp-watermark.gif



CodePen -- SVG Filter feTurbulence & feDisplacementMap 实现图片粒子化复原动画

动态改变 feDisplacementMap 的 scale 的参数实现一些开奖动效


基于上述的效果,我们可以实现这样一类效果,譬如一些开奖结果,一开始它是模糊的,但是用户点击之后,模糊的结果逐渐从模糊到真实。


但是点击事件,由于 SVG Animate 标签的一些限制,需要借助一些 Javascript 代码,这里借用 JQuery 简单做个示意。


我们有一串开奖数组 745846,实现点击之后从模糊到真实:


<div id="fe1" class="fe1">745846</div>
<svg>
    <filter id="feDisplacementMap" filterUnits="userSpaceOnUse" x="0" y="0" width="200" height="64">
        <feTurbulence type="fractalNoise" baseFrequency="0.0995" numOctaves="1" result="img" />
        <feDisplacementMap id="feDis" in="SourceGraphic" in2="img" scale="200" />
    </filter>
</svg>


$("#fe1").click((e) => {
    const filter = $("#feDis");
    const startTime = Date.now();
    const duration = 1000;
    const target = 200;
    requestAnimationFrame(function aniMove() {
        const t = Math.min(1, (Date.now() - startTime) / duration);
        const nextTarget = target - (t * target) + 1;
        filter.attr('scale', nextTarget);
        if (t < 1.0) {
            requestAnimationFrame(aniMove);
        }
    });
});


点击之前的状态如下:


b51684295b11479d999f5f70eb54f591_tplv-k3u1fbpfcp-zoom-1.png

点击之后:

ae2163e50f4b4261b97fe288ee63b549_tplv-k3u1fbpfcp-zoom-1.gif


上述效果,你可以套用到任何地方,完整的 Demo 地址:


CodePen Demo -- SVG Filter Button Effects


动态改变 feDisplacementMap 的 scale 的参数实现一些 fadeOut 动画


当然,上述的效果也是可以反着来的,就是一张图(或者任何元素),点击之后粒子化,然后渐变的消失,进阶版的 fadeOut 效果。


通过动态的改变滤镜的参数和图片的透明度,当然,也需要借助一些 JavaScript 代码,完整的代码就不贴了(与上述 DEMO 非常类似),直接上效果图:



image.png


image.png


是不是非常类似灭霸把人物消失的效果?之前看过这样一篇文章 - 谷歌灭霸彩蛋的效果实现,其中介绍了一种使用 Canvas 实现类似效果的方式,本文这里使用 SVG 滤镜达成了近似的效果。


对源码感兴趣的可以猛戳下面的 Demo,效果也是可以方便的移植到其他元素之上:

CodePen Demo -- 使用 SVG 滤镜实现任意元素粒子化 FadeOut 效果


不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特・梵高

目录
相关文章
|
6月前
|
人工智能
怎么用Midjourney制作表情包
怎么用Midjourney制作表情包
159 0
|
14天前
JS+SVG实现的滑块表情评价打分特效源码
JS+SVG实现的滑块表情评价打分特效源码是一段基于JS+SVG制作的表情评价打分效果代码,可以利用鼠标拖动滑块实现表情变化打分效果,支持手机端4个表情分段评价,会随着鼠标滑动的方向而变化
25 2
|
1月前
|
编解码 前端开发 JavaScript
ThreeJs制作模型图片
这篇文章介绍了如何使用Three.js将一张图片转化为3D场景中的像素化模型,通过提取图片的像素颜色并将它们应用到3D立方体上,形成一种特殊的图像展示效果。
26 0
ThreeJs制作模型图片
|
Web App开发 编解码 iOS开发
如何使用ffmpeg制作透明背景的视频
数字人的视频我是使用的腾讯智影生成带绿幕的视频,要实现透明背景,有个很关键的信息需要知道,不是所有的视频格式(视频编码)都支持透明背景,首先我们最常用的mp4就是不支持(不管是h264还是h265)都不支持,目前支持透明背景的只有少部分视频编码,比如google的vp9(webm)格式,上图中我用就是webm+vp9编码的视频。实测这种视频兼容性也不行,比如在苹果的safari浏览器下,就无法透明背景。
501 0
|
计算机视觉
【方便的Opencv】实现播放有声音的视频+附带图片生成gif
【方便的Opencv】实现播放有声音的视频+附带图片生成gif
【方便的Opencv】实现播放有声音的视频+附带图片生成gif
|
6月前
微信小游戏制作工具中关于背景图的设置
微信小游戏制作工具中关于背景图的设置
210 0
Photoshop利用置换滤镜制作文字人像
Photoshop利用置换滤镜制作文字人像
83 0
|
Web App开发 XML 编解码
Logo小变动,心境大不同,SVG矢量动画格式网站Logo图片制作与实践教程(Python3)
曾几何时,SVG(Scalable Vector Graphics)矢量动画图在坊间称之为一种被浏览器诅咒的技术,只因为糟糕的硬件支持(IE),和没完没了的兼容性调优(Safari)。但是在2022年的今天,一切都不一样了,正所谓三十年河东,三十年河西,微软所研发的采用Chromium内核作为IE替代者的Edge浏览器已经有望超越Safari成为第二大桌面浏览器,而曾经因为不支持关键帧动画被人诟病的Safari也统一了标准,市面上除了老帮菜IE,几乎所有平台(包括移动端)都已经对SVG足够友好,这让我们可以放心大胆的在网站上应用SVG矢量动画图。
Logo小变动,心境大不同,SVG矢量动画格式网站Logo图片制作与实践教程(Python3)
|
iOS开发 MacOS Windows
Unity2D像素游戏开发——Aseprite简单人物绘画+动画制作导出精灵表示例
Unity2D像素游戏开发——Aseprite简单人物绘画+动画制作导出精灵表示例
659 0
Unity2D像素游戏开发——Aseprite简单人物绘画+动画制作导出精灵表示例
|
计算机视觉 Python
Python3,4行代码给图片加美颜,拍照再也不需要开美颜滤镜了。
Python3,4行代码给图片加美颜,拍照再也不需要开美颜滤镜了。
35805 0
Python3,4行代码给图片加美颜,拍照再也不需要开美颜滤镜了。