写在最前面
做为一个技术人士来说,用什么样的技术解决什么的问题,相当重要。
对于本人来说,滤镜、渐变之类的简直就是玄学,但对于我的设计师同事来说,这些就是不值一提的常识。
那么,有没有必要去了解这些东西呢?
个人建议:需要知道这些知识能够发挥什么样的作用,用不着深入学习。
用经济学的术语就是深入学习滤镜之类的原理,是一种边际成本高,边际收入很低的行为,换言之就是性价比低。(我说的是对一般的开发者而言,如果是专门从事此领域就要再换言之一下了。)
但是完全不知道这一块的知识,也是不可取的,比如你完全不知道一些炫酷的特效如何产生的,那么你的思维空间就缺失掉了一部分的想象力,所以个人建议还是做个基本了解。现在进入正题:
简单说明
https://www.w3.org/TR/SVG/pservers.html#Gradients
虽然都是用来增强效果,但是三者还是有所区别:
- 图案和渐变通常用来做 fill, stroke 的填充。
- 滤镜通常是用来做填充之后的效果,比如阴影、反色之类的。
另外说明一下:定义区的东西,都需要使用属性来填写,比如 width="200"
不能使用 css {width:200}
否则无效!
渐变
渐变这个词你肯定听说过,不管是CSS3或是其它图像设计软件(PS)里面都有渐变概念,而且内容大致没什么差异。通常开发工具里面的取色板就是一个渐变的色盘。
不了解的可以先看两个例子
纯性渐变: https://www.w3.org/TR/SVG/images/pservers/lingrad01.svg
径向渐变: https://www.w3.org/TR/SVG/images/pservers/radgrad01.svg
其中,纯性渐变的代码如下,径向渐变就不贴了。
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1"
viewBox="0 0 300 200" >
<title>Example lingrag01</title>
<desc>Fill a rectangle using a linear-gradient paint server.</desc>
<defs>
<linearGradient id="MyGradient">
<stop offset="5%" stop-color="#A8F" />
<stop offset="95%" stop-color="#FDC" />
</linearGradient>
</defs>
<!-- The rectangle is filled using a linear-gradient paint server -->
<rect fill="url(#MyGradient)"
stroke="black"
stroke-width="2"
x="25" y="25" width="250" height="150"/>
</svg>
现在快速理解它们的基础属性:
纯性渐变
id
|
一般情况下给一下,好引用
|
|
x1,y1,x2,y2
|
字面意思
|
和线段<line>很像
|
gradientTransform
|
涂抹前进行转换,很少使用
|
支持CSS的transform属性字符,比如 "rotate(15)"
|
gradientUnits
|
定义(x1,y1,x2,y2的)坐标系
|
userSpaceOnUse | objectBoundingBox
userSpaceOnUse: SVG本身的坐标,1em,288px 等
objectBoundingBox : 相对填充物的坐标,如10%
|
spreadMethod
|
涂抹方法
|
pad | reflect | repeat
pad : 平铺,拉满屏幕
reflect : 正反反正正反反正正反反正
repeat : 正反正反正反正反正反正反
|
径向渐变
id
|
一般情况下给一下,好引用
|
|
cx,cy,r
|
起始中心点的设置
|
和圆<circle>很像
|
fx,fy,fr
|
焦点的设置
|
|
gradientTransform
|
涂抹前进行变换,很少使用
|
支持CSS的transform属性字符,比如 "rotate(15)"
|
gradientUnits
|
定义(cx,cy,r,fx,fy,fr的)坐标系。
|
userSpaceOnUse | objectBoundingBox
userSpaceOnUse: SVG本身的坐标,1em,288px 等
objectBoundingBox : 相对填充物的坐标,如10%
|
spreadMethod
|
涂抹方法
|
pad | reflect | repeat
pad : 平铺,拉满屏幕
reflect : 正反反正正反反正正反反正
repeat : 正反正反正反正反正反正反
|
其实可以看到两个渐变的不同点,就是坐标系和渐变方式的不一样:
- 线性渐变 : 从一个点到另一个点的渐变,两点之间的任意一点的颜色,应该就是用距离百分比衡量的两点之间的色差比。
- 径向渐变 : 从一个点到另一个点的渐变,两点之间会以半径为单位进行扩散色差。
子元素
两种渐变都需要包含一个子集:
offset | 可以是0-1的数字,也可以是0%到100%的比例值 |
---|---|
stop-color | 颜色值 |
stop-opacity | 0.0-1.0, 颜色的透明度 |
图案
图案也是一种填充的方式,比如我们常见的纹理地板,就是用一个很少的图案纵横重复多次得到的效果,图案的原理就是这样,特别适合于做纹理之类的填充。
id | 一般情况下给一下,好引用 | |
---|---|---|
x,y,width,height | 图案的坐标和大小 | |
viewBox | 图案本身的视口 | 比较少用,参考上节SVG说明 |
preserveAspectRatio | 图案本身的对齐、纵横比设置 | 比较少用,参考上节SVG说明 |
patternUnits | 图案的坐标系设置 | userSpaceOnUse |
patternContentUtils | 图案内容的坐标系设置 | userSpaceOnUse |
patternTransform | 图案涂抹前的变换 |
图案的属性和上面两个渐变的属性其实是很相近的,关键区别就是:
- 渐变标签下面需要有 一组
<stop>
进行颜色的变化设置 - 图案标签下面需要有 各种图形组合,比如
<path>
,<rect>
等等。
这里是一个在线的例子:https://www.w3.org/TR/SVG/images/pservers/pattern01.svg
代码如下:
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1"
viewBox="0 0 300 200" >
<title>Example pattern01</title>
<desc>Fill an ellipse using a pattern paint server.</desc>
<defs>
<pattern id="TrianglePattern"
patternUnits="userSpaceOnUse"
x="0" y="0" width="50" height="50"
viewBox="0 0 10 10" >
<path d="M 0 0 L 7 0 L 3.5 7 z"
fill="plum"
stroke="blue" />
</pattern>
</defs>
<!-- The ellipse is filled using a triangle pattern paint server -->
<ellipse fill="url(#TrianglePattern)"
stroke="black"
stroke-width="2"
cx="150" cy="100" rx="125" ry="75" />
</svg>
滤镜
渲染原理
先来理解一下滤镜是什么,你一定用过手机上的美化照片的软件,里面就有各式各样的滤镜,而SVG的滤镜和美图软件上的滤镜,从流程上来说,都是一样的,就这两步:
- 打开原始照片,进行第一次渲染。(原始SVG,浏览器进行计算,将数据存到内存)
- 选择滤镜,应用到原始照片上。(第二步:使用滤镜对内存中的数据进行叠加计算,显示出最终图像)
一般来说,使用滤镜的SVG性能会比较低,但它肯定是有好处的,比如我们看上去高大上的的阴影,灰化,朦胧,浮雕等特效,通过来说只需要一个滤镜就能搞定。(也可以这样说:如果你把美图软件的滤镜代码用SVG实现一遍,你也可以做出一个SVG版本的滤镜软件)
SVG使用滤镜性能低的原因:
SVG先要将失量图转换为临时位图,然后再使用滤镜对临时位图进行加工,每当SVG有变化时,这些计算过程就要重复一次。
当然前面也说了,滤镜这玩意不是码农们应该深入研究的东西,我们只要知道一些简单的内容即可,具体的细节就放心交给设计组同事吧。
其它小知识
首先以我这种初阶小白的水平介绍几个概念:
- 颜色(RGB模式)
- 颜色模式有很多,而适用于电脑屏幕(光源)的就是RGB颜色模式。
- 用 红Red、绿Green、蓝Blue,三种原色做为基本材料,进行叠加,形成的颜色
- 每个元色有256个刻度,从 0 至 255, 根据三个元色不同刻度上的叠加,RGB颜色模式总共就有 256x256x256 = 1600多万种颜色。
- 在程序中,我们用十六进制表示颜色。比如纯红色就是 #FF0000
- #000000 黑色就是三种颜色都为0 的叠加 ,#FFFFFF 白色就是三种颜色都为 255的叠加 (OXFF=255)
- 在代码中,如果三种原色十六位表示一样,比如 #AABBCC ,才能简写为 #ABC
- 通道
- 在RGB颜色的模式中,存在4个通道
- 第一个通道是RGB本身复合后的颜色通道
- 另外三个分别是 R,G,B 三元色的通道。
- 很多滤镜都可以只作用于指定通道上的像素,比如一个弱化红色的滤镜,可以选择通道为红色进行单独处理。
- 矩阵
- 这个解释起来比较麻烦,而且你也不一定要懂
- 一句话:矩阵就是映射,是程序里面常用的Map ,而且是双向都能GET的 Map.
- 比如说: 一个 #ccc 的数据通过一个矩阵后,就会变成 #ddd,那么一个 #ddd 的元素反向通过这个矩阵,就一定是 #ccc 。对此感兴趣建议自行深入了解线性代数。
- 颜色(HSL模式)
- 色相 Hue, 饱和度 Saturation 和 亮度 Lightness ,是以人类肉眼为观测的一种颜色模式
- 比如一个颜色觉得暗的话,只需要把L调高即可,如果觉得不够鲜艳,就增加S,觉得本身颜色就是错的,就调H
- 和RGB一样,HSL也有刻度,分别是0% - 100%,可以以小数点,所以,HSL模式可组合的颜色是无限的。
- 有些滤镜会以HSL模式进行参数优化,但最终会转换成RGB显示在屏幕。
滤镜结构
id
|
唯一ID
|
一般情况下给一个,好引用
|
x,y,width,height
|
相对空间,滤镜边界
|
这里说明一下:这里的值是相对于滤镜的主体的,比如要一个拉大的滤镜:
<filter x="-10%" y="-10%" width="120%" height="120%" />
|
filterUnits
|
定义坐标系
|
userSpaceOnUse | objectBoundingBox
userSpaceOnUse: SVG本身的坐标,1em,288px 等
objectBoundingBox : 相对填充物的坐标,如10%
|
primitiveUnits
|
滤镜基本单元单位
|
同上
|
滤镜的结构主要由三个步骤组成:
- 定义 : 各式各样的效果,后面会提到。
- 处理 :
、 , 并非必要步骤。 - 合并 :
,最终输出。
滤镜处理时,它的源输入为 “SourceGraphic”,可以使用源输入或其它滤镜处理后的输入做为一个滤镜的输入
对一个结果进行位移。
将两个滤镜合成一个滤镜,支持六种合成算法: over | in | out | atop | xor | arithmetic 。
<feComposite operator="xor" in="A" in2="B" />
也是合成滤镜的一种放式,并成时,颜色会按指定的参数进行计算。
SVG的滤镜最后面要有一个
效果型滤镜
https://www.w3.org/TR/filter-effects/
因为滤镜太多,应用太广,我也不便于举例子。可以自行Google体验一下各种滤镜的神奇效果。
在这罗列一下常用,及其一般的应用场景:
feGaussianBlur
|
高斯模糊
|
常用于做阴影,模糊化等。
|
feColorMatrix
|
通用颜色转换器
|
通过矩阵,对色值进行投射性转化,用处很多。
比如发光,投影,调色,等等。
但需要基础颜色知识以及线性代数的能力。
|
feImage
|
图片叠加
|
需要对图片进行再次滤镜时。
|
feComponentTransfer
|
各通道的调校包括
<feFuncR><feFuncG>
<feFuncB><feFuncA>
|
对于程序员来说,应该没什么用,更多用于照片处理吧。
用于对其中一个通道的调整,而不影响另外的通道。
|
feDiffuseLighting
|
漫反射
|
用于光照特效
|
feSpecularLighting
|
镜面反射
|
用于光照特效
|
fePointLight
|
点光源
|
用于光照特效
|
feDistantLight
|
近光源
|
用于光照特效
|
feSpotLight
|
聚光灯
|
用于光照特效
|
feFlood
|
填充纯色区域
|
区域性填充颜色
|
feTile
|
填充图案
|
区域性填充纹理
|
feMorghology
|
加厚、瘦身
|
zoom
|
feConvolveMatrix
|
改变邻近像素
|
浮雕等效果
|
feDisplacementMap
|
通道像素计算
|
调色
|
feTurbulence
|
通过Perlin noise方程计算
|
纹理
|
小结
这一小节感觉写的有点长了,突出了最长最没用的特性,如果你是来找炫酷的实例,也会感到失望。
关于滤镜的属性,也没有详细介绍,有深入学习的需求请参考 : https://www.w3.org/TR/filter-effects/