CSS滤镜效果
前言
CSS3
新增了filter
属性用来专门设置元素的滤镜效果,不过目前只支持两种类型:
- 内置的滤镜函数:一些很常用的滤镜效果。
url()
:该方法可以引用一个svg
滤镜元素来进行滤镜效果的设置。
CSS滤镜函数一览
滤镜函数 | 作用 | 参数 |
---|---|---|
blur() | 高斯模糊 | 模糊范围;<length> 类型数据,默认为0 ;不能为百分比!负值会被忽略; |
brightness() | 亮度调整 | 亮度值;小数或百分比 为 0 时全黑,为1 时图像不变 可以大于 1 ,大于1 时比原图像更亮 |
contrast() | 对比度调整 | 对比度值;值的设置同亮度一样 |
drop-shadow() | 阴影效果 | 参数设置同box-shadow() 类似 |
grayscale() | 灰度调整 | 灰度(线性)因子;值在0 - 1 之间 1 为完全的灰度图像,0 则不变 |
hue-rotate() | 色相旋转 | 色相旋转角度;单位为deg 或turn |
invert() | 颜色反转效果 | 反转(线性)因子;值在0 - 1 之间 1 为完全反转,0 则不变 |
opacity() | 不透明度调整 | 跟opacity 效果一样 |
saturate() | 饱和度调整 | 饱和度值;指的设置同亮度一样 |
sepia() | 褐色调整 | 褐色因子;设置同invert 1 为深褐色,0 则不变 |
滤镜详解
blur
blur()
方法的核心算法就是高斯滤波器(滤波器是计算机视觉/图像处理中的一个概念),即利用高斯函数(二维正态分布函数)算出以当前像素点为中心点的矩形区域内所有点的权重,然后将权重归一化处理,权重和各像素点颜色的乘积之和作为当前像素点的新颜色值;因此这种处理效果看起来就是模糊的图像;
上面就是二维正态分布函数,为标准差,对应的就是blur(length)
方法中的长度值,可以理解为滤波器的半径,当长度为时,得到的高斯权重矩阵大小就为;而则代表以当前像素点为原点,各个像素点的坐标;以blur(1px)
为例,此时,:
上面就是某个像素点和其周围相邻一个像素点之间的坐标值了;将坐标值和标准差代入公式即可得到每个像素点对应的权重值:
显然,权重值相加不等于1,因此需要做归一化处理:
细节问题一:模糊半径
从W3C
文档可知,它仅仅规范了高斯滤波器中标准差的来源,而没有说清楚模糊半径(即滤波器半径)怎么取;
The passed parameter defines the value of the standard deviation to the Gaussian function. The parameter is specified a CSS length, but does not accept percentage values. [1]
因此,blur()
方法规范在这一点上是不严谨的;但是MDN
上面对于blur()
方法中有个描述值得推敲:
The blur() fucntion applies a Gaussian blur to the input image. The value of radius defines the value of the standard deviation to the Gaussian function, or how many pixels on the screen blend into each other, so a larger value will create more blur. [2]
也就是说这个长度也可以用来描述模糊半径,由于这个长度可以是浮点数,但由于滤波器半径是整数,可以大胆推测:滤波器半径(模糊半径)是长度的向上取整值;
细节问题二:模糊效果超出部分
应用模糊滤镜效果时,可以看到模糊效果会向外扩张一定的区域,这个多出的区域大概就是传入blur
方法的长度:
1 | .test { |
1 | <div class="test"> |
不知模糊滤镜效果为何会超出原本的区域,看起来像是处理边界部分时进行相应宽度的填充导致的,不知道这算不算是副作用?毕竟一般的模糊滤镜处理效果是不会超出图像原本区域的,但是W3C
规范也并没有提及边界处理情况,所以有点迷;
当我们并不想要显示模糊滤镜超出的部分怎么办?传统的办法可以套一层父元素,然后利用overflow: hidden
进行隐藏;但是,其实有更简单的办法,那就是利用clip-path
直接将超出部分裁剪掉:
1 | .blur { |
brightness
亮度滤镜的原理很简单,就把亮度值与原像素值相乘,得到的像素值超出1
则为1
;其实这个效果很容易用混合模式中的正片叠底进行模拟(当然,亮度超出1
时就没法模拟了);
1 | <div class="brightness"> |
1 | .brightness-item { |
contrast
对比度滤镜计算公式如下:
这里,指的就是对比度系数,即传入contrast()
方法中的参数;因此,可以看出当对比度系数为1
时,得到图像就是原图像,当对比度系数为0
时,得到是纯灰度图像;当对比度系数超出1
时,得到的效果就是黑的越黑,白的更白,即对比度上升;
drop-shadow
A drop shadow is effectively a blurred, offset version of the input image’s alpha mask drawn in a particular color, composited below the image.[3]
由W3C
的定义可知,投影滤镜就是复制了图像的透明通道加上了投影颜色组成了新的图层,且在该图层上应用了模糊滤镜效果,该图层位于原图层的下方;
1 | <div class="drop"> |
1 | .drop-item { |
使用一张具有透明通道的图片,加上投影滤镜可以看到新的图层确实复制了原有的透明通道;
grayscale
灰度滤镜原理就很简单,就是将原像素颜色与其灰度值按比例进行混合:
hue-rotate
色相旋转,顾名思义就是将HSL
中的H
分量进行旋转;也就是先将颜色转为HSL
颜色,再将H
分量旋转指定量,然后再将颜色转回RGB
颜色;只要理解了HSL
色彩模型,就很容易这个色相旋转的本质了;
invert
反转滤镜的原理和灰度滤镜原理是类似的,就是将原像素颜色与其互补色按比例进行混合:
当然,如果是invert(1)
时(即完全的互补色),可以利用差值滤色模式来等价模拟:
1 | <div class="invert"> |
1 | .invert-item { |
saturate
饱和度滤镜原理同对比度类似,只不过需要先得出原像素颜色的明度值(即HSL
颜色中的L
分量),然后将明度值与原像素颜色按比例进行混合:
就是滤镜中设置的饱和度值,可以看出,当时,得到的就是一副灰度图像;
sepia
褐色滤镜本质上还是一个混合滤镜,只不过获取一个像素颜色对应的褐色需要多一点计算;不过由于没有在W3C
上发现有描述相关的算法,所以在网上找了褐色滤镜的算法[4]:
相关文档
- 你所不知道的 CSS 滤镜技巧与细节 · Issue #30 · chokcoco/iCSS
- filter - CSS(层叠样式表) | MDN
- 常用滤镜算法以及WebGL实现 | NewbieWeb
- FDCon2019大会分享之滤镜与混合模式实录 « 张鑫旭-鑫空间-鑫生活
- 图像处理的滤镜算法 - 掘金
- 高斯模糊的算法 - 阮一峰的网络日志
- https://en.wikipedia.org/wiki/Gaussian_blur
- 亮度,饱和度,对比度的计算方法_gaowebber的博客-CSDN博客_对比度计算公式