点击关注上方蓝字,阅读更多干货~
在日常开发中,对于图像不同效果的处理,通常需要设计侧的专业知识和技能,同时开发侧也需要增加额外的图片资源的请求。为了避免引入多个图片资源且和增加一些额外的配置项去实现不同效果的处理,我们可以使用CSS的滤镜属性直接对元素进行效果处理,而不需要对每个元素的不同效果引入相关的图片文件,从而能提高更大的灵活性和可维护性。
图1 奖励领取置灰效果图
filter滤镜就是css3新增的一个神奇功能,它可以对网页中的图片进行类似Photoshop图片处理的效果,但并不需要依赖于任何作图软件。同时,filter滤镜不仅可以对图片添加滤镜效果,还可以对网页元素甚至视频进行滤镜处理。
filter: <filter-function> [<filter-function>]* | none
filter: url(file.svg#filter-element-id)
blur(radius)函数将高斯模糊应用到图像。radius 定义了高斯函数的标准偏差值,或者屏幕上有多少像素相互融合,值越大模糊程度越高。若未设置值,默认为 0。
brightness(amount)函数让图像更明亮或更暗淡。值为 0% 将创建全黑图像,值为 100% 会使输入保持不变,值大于 100% 提供更明亮的结果。若未设置值,默认为 1。
图3 brightness滤镜效果对比图
contrast(amount)函数可调整输入图像的对比度。值是 0% 图像会全黑,值为100% 图像不变,值可以超过 100%,意味着会运用更低的对比。若未设置值,默认是 1。
图4 contrast滤镜效果对比图
drop-shadow(offset-x offset-y blur-radius color) 可在图像后方应用投影。阴影可以设置模糊度,以特定颜色画出的遮罩图的偏移版本,最终合成在图像下面。
图5 drop-shadow滤镜效果对比图
grayscale(amount)函数可将图像转为灰度图。amount的值定义了转换的比例,值在 0% 到 100% 之间,值为 0% 图像无变化,值为 100%则完全转为灰度图像。若未设置值,默认是 0。
图6 grayscale滤镜效果对比图
图7 hue-rotate滤镜效果对比图
图8 invert滤镜效果对比图
opacity(amount) 函数可改变图像透明度。amount的值定义转换的比例,值在 0% 和 100% 之间,值为 0% 则是完全透明,值为 100% 则图像无变化。若未设置值,则默认为 1。该函数与css的opacity 属性很相似,不同之处在于通过 filter,一些浏览器为了提升性能会提供硬件加速。
图9 opacity滤镜效果对比图
saturate(amount)函数可转换图像饱和度。amount的值定义转换的比例,值为 0% 则是完全不饱和,值为 100% 则图像无变化,超过 100% 则有更高的饱和度。若未设置值,则默认为 1。
图10 saturate滤镜效果对比图
sepia(amount) 函数可将图像转换为深褐色。amount的值定义转换的比例,值在 0% 到 100% 之间,值为 0% 图像无变化,值为 100% 则完全是深褐色的。若未设置值,则默认为 0。
图11 sepia滤镜效果对比图
从filter函数的使用方式可以看出,滤镜效果是可以进行叠加的,比如,filter: contrast(50%) brightness(50%)。
图12 组合滤镜效果图
那么同一元素上定义多个滤镜的话,滤镜的先后顺序对最后效果有影响吗?我们调换滤镜顺序换成filter: brightness(50%) contrast(50%)来看看。
图13 组合滤镜顺序变换效果图
文字融合动画就是一种文字从融合到分开的效果,我们可以通过改变letter-spacing和blur的值去进行效果实现。
<div class="container">
<div class="text">Hello World</div>
</div>
.container {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #000;
filter: contrast(30);
}
.text {
color: #fff;
font-size: 100px;
animation: show 3s linear forwards;
}
@keyframes show {
0% {
opacity: 0;
letter-spacing: -50px;
filter: blur(10px);
}
25% {
opacity: 1;
filter: blur(8px);
}
50% {
filter: blur(5px);
}
100% {
letter-spacing: 10px;
filter: blur(2px);
}
}
<div class="g-container">
<div class="g-number">90%</div>
<div class="g-contrast">
<div class="g-circle"></div>
<ul class="g-bubbles">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
.g-container {
position: relative;
width: 300px;
height: 400px;
margin: auto;
}
.g-number {
position: absolute;
top: 100px;
width: 100%;
color: #fff;
font-size: 30px;
text-align: center;
z-index: 10;
}
.g-contrast {
width: 100%;
height: 100%;
background-color: #000;
overflow: hidden;
filter: contrast(10) hue-rotate(0);
animation: hueRotate 10s infinite linear;
}
.g-circle {
position: relative;
width: 300px;
height: 300px;
box-sizing: border-box;
filter: blur(8px);
}
.g-circle::after {
content: "";
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%) rotate(0);
width: 200px;
height: 200px;
background-color: #00ff6f;
border-radius: 42% 38% 62% 49%/45%;
animation: rotate 10s infinite linear;
}
.g-circle::before {
content: "";
position: absolute;
width: 176px;
height: 176px;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
background-color: #000;
z-index: 10;
}
.g-bubbles {
position: absolute;
left: 50%;
bottom: 0;
width: 100px;
height: 40px;
transform: translate(-50%, 0);
border-radius: 100px 100px 0 0;
background-color: #00ff6f;
filter: blur(5px);
}
li {
position: absolute;
border-radius: 50%;
background: #00ff6f;
}
li:nth-child(0) {
left: 50px;
top: 50%;
transform: translate(-50%, -50%);
width: 16px;
height: 16px;
animation: move 4s ease-in-out -1.47s infinite;
}
li:nth-child(1) {
left: 55px;
top: 50%;
transform: translate(-50%, -50%);
width: 18px;
height: 18px;
animation: move 6s ease-in-out -2.23s infinite;
}
li:nth-child(2) {
left: 60px;
top: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
animation: move 5s ease-in-out -3.89s infinite;
}
li:nth-child(3) {
left: 65px;
top: 50%;
transform: translate(-50%, -50%);
width: 22px;
height: 22px;
animation: move 7s ease-in-out -4.56s infinite;
}
li:nth-child(4) {
left: 70px;
top: 50%;
transform: translate(-50%, -50%);
width: 24px;
height: 24px;
animation: move 9s ease-in-out -2.12s infinite;
}
li:nth-child(5) {
left: 75px;
top: 50%;
transform: translate(-50%, -50%);
width: 26px;
height: 26px;
animation: move 9s ease-in-out -1.98s infinite;
}
li:nth-child(6) {
left: 80px;
top: 50%;
transform: translate(-50%, -50%);
width: 23px;
height: 23px;
animation: move 5s ease-in-out -3.35s infinite;
}
li:nth-child(7) {
left: 63px;
top: 50%;
transform: translate(-50%, -50%);
width: 19px;
height: 19px;
animation: move 7s ease-in-out -4.34s infinite;
}
li:nth-child(8) {
left: 67px;
top: 50%;
transform: translate(-50%, -50%);
width: 25px;
height: 25px;
animation: move 6s ease-in-out -2.87s infinite;
}
li:nth-child(9) {
left: 73px;
top: 50%;
transform: translate(-50%, -50%);
width: 28px;
height: 28px;
animation: move 8s ease-in-out -3.45s infinite;
}
li:nth-child(10) {
left: 56px;
top: 50%;
transform: translate(-50%, -50%);
width: 24px;
height: 24px;
animation: move 7s ease-in-out -1.83s infinite;
}
li:nth-child(11) {
left: 45px;
top: 50%;
transform: translate(-50%, -50%);
width: 25px;
height: 25px;
animation: move 5s ease-in-out -2.67s infinite;
}
li:nth-child(12) {
left: 68px;
top: 50%;
transform: translate(-50%, -50%);
width: 19px;
height: 19px;
animation: move 6s ease-in-out -3.12s infinite;
}
li:nth-child(13) {
left: 54px;
top: 50%;
transform: translate(-50%, -50%);
width: 29px;
height: 29px;
animation: move 9s ease-in-out -2.22s infinite;
}
li:nth-child(14) {
left: 41px;
top: 50%;
transform: translate(-50%, -50%);
width: 27px;
height: 27px;
animation: move 5s ease-in-out -1.11s infinite;
}
li:nth-child(15) {
left: 51px;
top: 50%;
transform: translate(-50%, -50%);
width: 24px;
height: 24px;
animation: move 7s ease-in-out -3.23s infinite;
}
@keyframes rotate {
50% {
border-radius: 45%/42% 38% 58% 49%;
}
100% {
transform: translate(-50%, -50%) rotate(720deg);
}
}
@keyframes move {
90% {
opacity: 1;
}
100% {
opacity: 0.1;
transform: translate(-50%, -180px);
}
}
@keyframes hueRotate {
100% {
filter: contrast(15) hue-rotate(360deg);
}
}
图14 手机充电动画效果图
<div class="main">
<div class="img"></div>
<div class="text">Thank you for watching!</div>
</div>
.main {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: #000;
}
.img {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background: url("xxx.png");
background-size: cover;
animation: imgHide 3s linear forwards;
}
.text {
color: #fff;
font-size: 50px;
opacity: 0;
animation: textShow 2s linear forwards;
}
@keyframes imgHide {
0% {
filter: brightness(1);
}
100% {
filter: brightness(0);
}
}
@keyframes textShow {
0% {
opacity: 0;
filter: blur(8px) brightness(50%);
}
100% {
opacity: 1;
filter: blur(0) brightness(100%);
}
}
<div>MAINTO MEMBER CENTER</div>
div {
font-size: 80px;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(to right, red, orange, yellow, green, cyan, blue, purple);
animation: huerotate 6s linear infinite;
}
@keyframes huerotate {
from { filter: hue-rotate(0deg); }
to { filter: hue-rotate(360deg); }
}
效果图片如下所示:
div {
background: linear-gradient(45deg, #5fddcc, #ff004d);
animation: hueRotate 10s infinite alternate;
}
@keyframes hueRotate {
0 {
filter: hue-rotate(0);
}
100% {
filter: hue-rotate(360deg);
}
}
图16 动态背景颜色变换效果图
这些通过CSS动画或JavaScript控制去实时改变元素上的滤镜效果,从而在页面上产生动态变化的视觉效果又叫做动态滤镜效果,那与之相对应的不会发生改变或动态变化自然就是静态滤镜效果。静态滤镜效果在开发中经常被使用,下面我们就来聊聊在日常营销业务中的一些常见的静态滤镜的使用场景。
html {
filter: grayscale(.95);
}
.unactive {
filter: brightness(0.5);
}
.active {
filter: brightness(1);
}
图18 集卡明暗效果图
打个比方我们需要给下面的卡券图片再加个阴影效果:
图19 卡券图片
设置阴影的方式我们脑子里肯定首先就会想到box-shadow属性,我们先来看看它的的使用方式。
box-shadow: offset-x offset-y blur spread color inset;
box-shadow: 2px 4px 3px rgba(50, 50, 0, 0.5);
图20 卡券图片box-shadow效果图
如上图阴影是加了,但是好像哪里不太对,为什么直接给图片外围增加了一个阴影,并没有在卡券本身添加阴影呢?
filter: drop-shadow(2px 4px 3px rgba(50, 50, 0, 0.5));
图21 卡券图片drop-shadow效果图
如上图才是我们期望的效果,阴影效果只作用到卡券本身,这说明drop-shadow的阴影效果是可以穿透透明元素的。除此之外,通过滤镜一些浏览器为了更好的性能会提供硬件加速。但是在使用drop-shadow的投影时,需要注意的是任何非透明的部分都会被打上投影,包括文本(如果背景是透明的)。
图22 drop-shadow效果对比图
毛玻璃效果是一种常见的视觉效果,它模拟了玻璃表面上由于光线折射而产生的模糊和透明感。我们经常需要使用毛玻璃效果处理内容模糊,以此达到一个信息保护的效果,或者进行背景模糊突出主要内容,引导用户进行操作,在日常开发中其实就是使用了filter的blur属性进行实现的。比如说我们需要给一些产品卡片设置毛玻璃效果:
图23 毛玻璃效果范围超出对比图
使用filter添加模糊后,实际看到的大小会超出我们设置的宽高,这是由于周围的毛边效果产生的,我们可以通过外层设置 overflow: hidden进行处理。不过其实使用filter实现的毛玻璃效果并不是唯一且最好的方式,我们也可以用backdrop-filter属性去实现漂亮的毛玻璃效果,我们来看看他们的实现效果有什么区别。
图24 毛玻璃效果对比图
图25 毛玻璃效果元素结构对比图
由元素结构可以看出,使用backdrop-filter的效果确实比使用filter的效果多了一层置于图片上层的元素,blur效果也并不是作用于图片本身,而是作用于图片的上层元素。
没错,backdrop-filter并不是通过处理图片本身来实现毛玻璃的效果,而是通过在图片上面盖上一个模糊层从而达到毛玻璃的效果,因此要做模糊处理的图片必须置于使用backdrop-filter元素的下面。
backdrop-filter可以给元素后面区域添加图形效果(如模糊或颜色偏移),而filter属性是将模糊或颜色偏移等图形效果应用于元素。虽然backdrop-filter使用方式同filter属性一致,但它适用于元素背后的所有元素,不过为了看到效果,必须使元素或其背景至少部分透明。
属性值 | filter | drop-filter | 说明 |
blur | 支持 | 支持 | 高斯模糊 |
brightness | 支持 | 支持 | 亮度 |
contrast | 支持 | 支持 | 对比度 |
drop-shadow | 支持 | 支持 | 阴影 |
grayscale | 支持 | 支持 | 灰度 |
hue-rotate | 支持 | 支持 | 色相 |
invert | 支持 | 支持 | 反相 |
opacity | 支持 | 支持 | 透明度 |
sepia | 支持 | 支持 | 饱和度 |
saturate | 支持 | 支持 | 褐色 |
url | 支持 | 支持 | SVG过滤器的URL |
<div class="main">
<div class="child">none</div>
<div class="child filter">filter</div>
<div class="child backdrop-filter">backdrop-filter</div>
</div>
.main {
width:100vw;
height:100vh;
display: flex;
align-items: center;
justify-content: center;
background: url("xxx.png");
background-size: cover;
}
.child {
width: 400px;
height:300px;
color: #fff;
font-size: 20px;
text-align: center;
line-height: 300px;
background: rgba(0, 0, 0, .7);
margin-left: 20px;
}
.filter {
filter: blur(8px);
}
.backdrop-filter {
backdrop-filter: blur(8px);
}
图26 滤镜作用元素效果对比图
图27 filter兼容性说明图
filter属性在现代浏览器中有很好的支持,包括Chrome、Firefox、Safari、Edge等主流浏览器,部分版本仍需要添加前缀进行兼容性处理。
图28 dropback-filter兼容性说明图
由上可知,filter属性在大部分浏览器中具有良好的兼容性,但只能调整元素本身的效果;backdrop-filter属性适用于调整元素后面内容的效果,但兼容性相对较差。所以还是需要根据具体的需求和是否需要广泛支持的场景,选择适合的属性去进行对应滤镜效果的处理。
在本文中,我们先介绍了各种滤镜函数的基础用法和显示效果,了解了它们如何改变元素的外观和视觉表现。随后,我们了解了如何通过灵活地应用不同的滤镜函数和组合,去创造出更复杂、个性化的滤镜效果,去实现图像处理和动画,为网页设计增添了更多创意和动感。我们还知道了通过使用filter属性,可以简单地应用模糊(blur)、对比度(contrast)和亮度(brightness)调整、颜色调整等效果,让网页元素瞬间焕发生机。而backdrop-filter属性则允许我们对元素背景内容进行处理,为网页带来更深度的视觉层次。
但是,在使用滤镜效果时我们也要考虑兼容性和性能问题,尽量避免过度使用滤镜造成页面加载缓慢。虽然大多数现代浏览器都支持CSS滤镜,但一些高级滤镜在较旧的浏览器或移动设备上可能会有兼容性问题。因此,我们在使用滤镜时需要进行兼容性测试,并在必要时提供备用方案,以确保在不同平台和设备上都能展现良好的效果。
本文作者
柯琦,来自缦图互联网中心前端团队。
--------END--------
也许你还想看