X.d 笔记

小Web,大世界

0%

SVG简单入门四:渐变、图案及滤镜

写在最前面

做为一个技术人士来说,用什么样的技术解决什么的问题,相当重要。

对于本人来说,滤镜、渐变之类的简直就是玄学,但对于我的设计师同事来说,这些就是不值一提的常识。

那么,有没有必要去了解这些东西呢?

个人建议:需要知道这些知识能够发挥什么样的作用,用不着深入学习。

用经济学的术语就是深入学习滤镜之类的原理,是一种边际成本高,边际收入很低的行为,换言之就是性价比低。(我说的是对一般的开发者而言,如果是专门从事此领域就要再换言之一下了。)

但是完全不知道这一块的知识,也是不可取的,比如你完全不知道一些炫酷的特效如何产生的,那么你的思维空间就缺失掉了一部分的想象力,所以个人建议还是做个基本了解。现在进入正题:

简单说明

https://www.w3.org/TR/SVG/pservers.html#Gradients

虽然都是用来增强效果,但是三者还是有所区别:

  1. 图案和渐变通常用来做 fill, stroke 的填充。
  2. 滤镜通常是用来做填充之后的效果,比如阴影、反色之类的。

另外说明一下:定义区的东西,都需要使用属性来填写,比如 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 : 正反正反正反正反正反正反

其实可以看到两个渐变的不同点,就是坐标系和渐变方式的不一样:

  1. 线性渐变 : 从一个点到另一个点的渐变,两点之间的任意一点的颜色,应该就是用距离百分比衡量的两点之间的色差比。
  2. 径向渐变 : 从一个点到另一个点的渐变,两点之间会以半径为单位进行扩散色差。

子元素

两种渐变都需要包含一个子集: 的标签组。每个stop 的核心属性如下:

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 图案涂抹前的变换

图案的属性和上面两个渐变的属性其实是很相近的,关键区别就是:

  1. 渐变标签下面需要有 一组 <stop> 进行颜色的变化设置
  2. 图案标签下面需要有 各种图形组合,比如 <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的滤镜和美图软件上的滤镜,从流程上来说,都是一样的,就这两步:

  1. 打开原始照片,进行第一次渲染。(原始SVG,浏览器进行计算,将数据存到内存)
  2. 选择滤镜,应用到原始照片上。(第二步:使用滤镜对内存中的数据进行叠加计算,显示出最终图像)

一般来说,使用滤镜的SVG性能会比较低,但它肯定是有好处的,比如我们看上去高大上的的阴影,灰化,朦胧,浮雕等特效,通过来说只需要一个滤镜就能搞定。(也可以这样说:如果你把美图软件的滤镜代码用SVG实现一遍,你也可以做出一个SVG版本的滤镜软件)

SVG使用滤镜性能低的原因:
SVG先要将失量图转换为临时位图,然后再使用滤镜对临时位图进行加工,每当SVG有变化时,这些计算过程就要重复一次。

当然前面也说了,滤镜这玩意不是码农们应该深入研究的东西,我们只要知道一些简单的内容即可,具体的细节就放心交给设计组同事吧。

其它小知识

首先以我这种初阶小白的水平介绍几个概念:

  1. 颜色(RGB模式)
    1. 颜色模式有很多,而适用于电脑屏幕(光源)的就是RGB颜色模式。
    2. 用 红Red、绿Green、蓝Blue,三种原色做为基本材料,进行叠加,形成的颜色
    3. 每个元色有256个刻度,从 0 至 255, 根据三个元色不同刻度上的叠加,RGB颜色模式总共就有 256x256x256 = 1600多万种颜色。
    4. 在程序中,我们用十六进制表示颜色。比如纯红色就是 #FF0000
    5. #000000 黑色就是三种颜色都为0 的叠加 ,#FFFFFF 白色就是三种颜色都为 255的叠加 (OXFF=255)
    6. 在代码中,如果三种原色十六位表示一样,比如 #AABBCC ,才能简写为 #ABC
  2. 通道
    1. 在RGB颜色的模式中,存在4个通道
    2. 第一个通道是RGB本身复合后的颜色通道
    3. 另外三个分别是 R,G,B 三元色的通道。
    4. 很多滤镜都可以只作用于指定通道上的像素,比如一个弱化红色的滤镜,可以选择通道为红色进行单独处理。
  3. 矩阵
    1. 这个解释起来比较麻烦,而且你也不一定要懂
    2. 一句话:矩阵就是映射,是程序里面常用的Map ,而且是双向都能GET的 Map.
    3. 比如说: 一个 #ccc 的数据通过一个矩阵后,就会变成 #ddd,那么一个 #ddd 的元素反向通过这个矩阵,就一定是 #ccc 。对此感兴趣建议自行深入了解线性代数。
  4. 颜色(HSL模式)
    1.  色相 Hue, 饱和度 Saturation 和 亮度 Lightness ,是以人类肉眼为观测的一种颜色模式
    2. 比如一个颜色觉得暗的话,只需要把L调高即可,如果觉得不够鲜艳,就增加S,觉得本身颜色就是错的,就调H
    3. 和RGB一样,HSL也有刻度,分别是0% - 100%,可以以小数点,所以,HSL模式可组合的颜色是无限的。
    4. 有些滤镜会以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
滤镜基本单元单位
同上

滤镜的结构主要由三个步骤组成:

  1. 定义 :  各式各样的效果,后面会提到。
  2. 处理 : 并非必要步骤。
  3. 合并 : ,最终输出。

滤镜处理时,它的源输入为 “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/