踏足SVG 深入浅出全方位介绍SVG的功能及特性 - 滤镜篇(二)

804 阅读5分钟

前言

上一篇文章中介绍了什么是滤镜、滤镜的容器和最常见的高斯滤镜及其基本应用。这篇文章将介绍几个常用的滤镜 feImagefeFloodfeOffsetfeDropShadowfeColorMatrix。结合示例,来详细说明每个滤镜的使用方法。

往期文章

踏足SVG | 深入浅出全方位介绍SVG的功能及特性 - 基础篇

踏足SVG 深入浅出全方位介绍SVG的功能及特性 - 滤镜篇(一)

feImage 获取图像数据作为输出

feImage滤镜从外部来源取得图像数据,并提供像素数据作为输出(意味着如果外部来源是一个SVG图像,这个图像将被栅格化。)

属性:

xlink:href:图像的地址 preserveAspectRatio: 图像的缩放的表现模式

例:引入外部图片与外部 SVG 图像

<svg width="200" height="200" viewBox="0 0 200 200">
  <defs>
    <filter id="image">
      <!-- feImage 引入外部图片 -->
      <feImage xlink:href="../../image/VIP.png"/>
    </filter>
    <filter id="image2">
      <!-- feImage 引入外部 svg -->
      <feImage xlink:href="../../static/PPT.svg#ppt"/>
    </filter>
  </defs>
  <rect x="10" y="10" width="80" height="80" fill="green" filter="url(#image)" />
  <rect x="10" y="100" width="80" height="80" fill="green" filter="url(#image2)" />
</svg>

image.png

两者差别不大,需要注意的是引入 svg 需要指定 svg 容器 id

preserveAspectRatio 图像的缩放的表现模式

在一个容器中展示某个图片或者内容是,如果容器大小不够,无法完整的放置想要展示的内容,这个时候可以通过设置这个属性来告诉容器改如何展示内容。

preserveAspectRatio 是一个符合属性,需要指定 对齐方式缩放模式

对齐方式

  • none
  • xMinYMin
  • xMidYMin
  • xMaxYMin
  • xMinYMid
  • xMidYMid (默认值)
  • xMaxYMid
  • xMinYMax
  • xMidYMax
  • xMaxYMax

看起来很多其实并不难,这里其实就是指定了图片的位置。换个说法就会发现非常简单

  • none: 不进行统一缩放,图片会按容器大小被拉伸
  • xMin:水平方向左对齐
  • xMid:水平方向居中
  • xMax:水平方向右对齐
  • YMin:竖直方向顶部对齐
  • YMid:竖直方向居中
  • YMax: 竖直方向底部对齐

举几个例子

xMinYMin:水平方向左对齐,竖直方向顶部对齐。所以图片会在左上角 xMaxYMid:水平方向右对齐,竖直方向居中。所以图片会靠右侧竖直居中

缩放模式

  • meet: 展示内容部分会优先占满短边进行等比缩放,会尽可能完整的展示内容。
  • slice:展示内容部分会优先占满长边进行等比缩放,展示内容可能展示不完全,会超出容器

全部情况的展示对比

具体的代码比较多,最后会在整个系列整理完成之后统一开源。留给有缘人。

image.png

image.png

image.png

feFlood 指定滤镜的填充

属性:

  • flood-color: 填充的颜色
  • flood-opacity: 填充的透明度

简单使用:

  .border{
    display: inline-block;
    border: 1px solid #000;
  }
  .img {
    display: block;
    width: 100px;
    height: 100px;
  }
  .filter-svg{
    filter: url("#MyFilter");
  }
<svg width="100" height="100" viewBox="0 0 100 100">
  <defs>
    <filter id="MyFilter">
      <feFlood x="0" y="0" flood-color="green" flood-opacity="0.5"/>
    </filter>
  </defs>
  <!-- 通过滤镜给矩形添加填充 -->
  <rect x="10" y="10" width="80" height="80" filter="url(#MyFilter)" />
</svg>
<!-- 这里滤镜的填充图形替换了原有的图片内容 -->
<img src="../../image/VIP.png" class="img filter-svg" alt="" />

image.png

feOffset 指定输入图像的偏移量

属性:

  • in:数据输入源
  • dx:x方向上的偏移量
  • dy:y方向上的偏移量

简单使用

<svg class="border" width="200" height="200" viewBox="0 0 200 200" style="display: none;">
  <defs>
    <filter id="MyFilter" >
      <feOffset in="SourceGraphic" dx="20" dy="20" />
    </filter>
    <filter id="MyFilter2" >
      <!-- in 可以不传,默认为 SourceGraphic -->
      <feOffset dx="20" dy="20" />
    </filter>
  </defs>
</svg>
<div class="border">
  <img src="../../image/VIP.png" alt="" style="filter: url(#MyFilter);">
</div>
<div class="border">
  <img src="../../image/VIP.png" alt="" style="filter: url(#MyFilter2);">
</div>

image.png

feDropShadow 图像投影

该滤镜对输入图像进行投影。所以透明的不会被投射出来。其结果同 css 滤镜中的 drop-shadow。

属性:

  • dx: 此属性定义投影的 x 偏移量。
  • dy: 此属性定义投影的 y 偏移量。
  • stdDeviation: 定义模糊操作的标准差,值越大越模糊。20以上基本上就看不到了
  • flood-color: 投影的颜色(feFlood,的专有属性,在此也可以使用)
  • flood-opacity: 投影的透明度(feFlood,的专有属性,在此也可以使用)

简单使用

<svg width="100" height="100" viewBox="0 0 100 100">
  <defs>
    <filter id="dropShadow">
      <feDropShadow  dx="8" dy="8" flood-color="red" flood-opacity="0.5" stdDeviation="2" />
    </filter>
  </defs>
</svg>
<img src="../../image/处女座.png" class="img filter-svg" alt="" />

image.png

feColorMatrix 图像矩阵变换

该滤镜基于转换矩阵对颜色进行变换。每一像素的颜色值(一个表示为[红,绿,蓝,透明度] 的矢量) 都经过矩阵乘法 (matrix multiplated) 计算出的新颜色。

属性:

  • type: 类型。有预设的矩阵作为特定类型可供选择,你也可以通过 matrix 来自己写矩阵函数
  • values: 值。不同类型所对应的值不一致

type:saturate

改变图像的饱和度,效果同 filter: saturate

value: 标准值在 0 - 1 之间。超过 1 饱和度叠加递增

例子:

<svg>
  <defs>
    <filter id="saturate">
      <feColorMatrix id="saturateMatrix" in="SourceGraphic" type="saturate" values="0.2"/>
    </filter>
  </defs>
</svg>

<h4>saturate</h4>
<img class="img saturate"  src="../../image/VIP.png" alt="">
0-1之间
<input id="saturateInput" value="0.2" onchange="change(event,'saturate')" type="text">

修改 values 属性(后面的例子也有使用,就不一一列举)

  function change(e,type,_value){
    const value = e.target.value;
    const target = document.getElementById(type + 'Matrix');
    target.attributes.values.value = _value || value;
  }

给图片设置滤镜(后面的例子也有使用,就不一一列举)

  .img {
    display: block;
    width: 200px;
    height: 250px;
  }
  .saturate{
    filter: url("#saturate");
  }

saturate.gif

type:hueRotate

色环旋转,效果同 filter: hue-rotate。

value: 角度值。 同样的超过 360° 等于重新开始了一圈。

例子:

<filter id="hueRotate">
  <feColorMatrix id="hueRotateMatrix" in="SourceGraphic" type="hueRotate" values="100"/>
</filter>

<h4>hueRotate</h4>
<img class="img hueRotate"  src="../../image/VIP.png" alt="">
角度值
<input id="hueRotateInput" value="100" onchange="change(event,'hueRotate')" type="text">

hueRotate.gif

type:luminanceToAlpha

阿尔法亮度,没有 value 值

例子

<filter id="luminanceToAlpha">
 <feColorMatrix in="SourceGraphic" type="luminanceToAlpha"/>
</filter>

<h4>luminanceToAlpha</h4>
<img class="img luminanceToAlpha"  src="../../image/VIP.png" alt="">

image.png

type:matrix

颜色矩阵(估计要些美术知识),像素级的绘制图像

value: 矩阵值。是一个 4 * 5 的矩阵值

R G B A 1
1 0 0 0 0 => R = 1*R + 0*G + 0*B + 0*A + 0
0 1 0 0 0 => G = 0*R + 1*G + 0*B + 0*A + 0
0 0 1 0 0 => B = 0*R + 0*G + 1*B + 0*A + 0
0 0 0 1 0 => A = 0*R + 0*G + 0*B + 1*A + 0

matrix 可以实现 feColorMatrix 其他 type 类型的效果。同时可以自己设置矩阵,以达到更丰富的效果。

原像矩阵

<filter id="matrix">
  <feColorMatrix in="SourceGraphic" type="matrix" 
    values="1 0 0 0 0
            0 1 0 0 0
            0 0 1 0 0
            0 0 0 1 0" 
  />
<div>原像矩阵</div>
<img class="img matrix"  src="../../image/VIP.png" alt="">

image.png

透明

<filter id="matrix2">
  <feColorMatrix in="SourceGraphic" type="matrix" 
    values="1 0 0 0 0
            0 1 0 0 0
            0 0 1 0 0
            0 0 0 .2 0" 
  />
</filter>
<div>透明</div>
<img class="img matrix2"  src="../../image/VIP.png" alt="">

image.png

单色增强

<filter id="matrix3">
  <feColorMatrix in="SourceGraphic" type="matrix" 
    values="1 0 0 0 .5
            0 1 0 0 0
            0 0 1 0 0
            0 0 0 1 0" 
  />
</filter>
<div>单色增强(这里例子用的是红色)</div>
<img class="img matrix3"  src="../../image/VIP.png" alt="">

image.png

暗色

<filter id="matrix4">
  <feColorMatrix in="SourceGraphic" type="matrix" 
    values=".2 0 0 0 0
            0 .2 0 0 0
            0 0 .2 0 0
            0 0 0 1 0" 
  />
</filter>
<div>暗度</div>
<img class="img matrix4"  src="../../image/VIP.png" alt="">

image.png

灰白

<filter id="matrix5">
  <!-- 这里矩阵前面 3 x 3 的小矩阵同值就能保证最后输出的值颜色相同。 -->
  <!-- 但是输出值越接近 1 图像越亮。原因就是最后的 rgb 位置的值远大于 1 所以图片太白了就显示不出东西了。所以我给了个 -0.5 的控制量看得清除点 -->
  <feColorMatrix in="SourceGraphic" type="matrix" 
    values=".5 .5 .5 0 -0.5
            .5 .5 .5 0 -0.5
            .5 .5 .5 0 -0.5
            0 0 0 1 0" 
  />
  <!-- values="1 1 1 0 0
            1 1 1 0 0
            1 1 1 0 0
            0 0 0 1 0"  -->
</filter>

<div>灰白 => rgb 同值图像变灰</div>
<img class="img matrix5"  src="../../image/VIP.png" alt="">

image.png

颜色增强

<filter id="matrix6">
  <feColorMatrix in="SourceGraphic" type="matrix" 
    values="1.2 0 0 0 0
            0 1.2 0 0 0
            0 0 1.2 0 0
            0 0 0 1 0" 
  />
</filter>
<div>颜色增强</div>
<img class="img matrix6"  src="../../image/VIP.png" alt="">

image.png

颜色修改

<filter id="matrix7">
  <feColorMatrix id="colorMatrix" in="SourceGraphic" type="matrix" 
    values="0 0 0 0 1
            0 0 0 0 0
            0 0 0 0 0
            0 0 0 1 0" 
  />
</filter>

<div>颜色修改</div>
<img class="img matrix7"  src="../../image/处女座.png" alt="">
<label>红:<input type="radio" checked="checked" name="color" value="1" onchange="change(event,'color','0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0')"/></label>
<label>绿:<input type="radio" name="color" value="2" onchange="change(event,'color','0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0')"/></label>
<label>蓝:<input type="radio" name="color" value="3" onchange="change(event,'color','0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0')"/></label>

colorMatrix2.gif

最后

参考资料

参考来源 - MDN