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

前言

本篇文章将介绍SVG的光源滤镜。包括: 用来描述光源反射方式的feDiffuseLightingfeSpecularLighting,以及用来描述光源的 fePointLightfeDistantLightfeSpotLight。并且将会通过一些实际的使用案例来详细说明。

人为什么能看到光

首先,在介绍和使用这些滤镜的时候,我们需要明白一个原理。人为什么能够看到东西?

在现实生活中,太阳发出的光照射到物体上,被照射的物体会吸收一部分光,并将剩余的光反射出去。人的眼睛接受到物体反射来的光,经过大脑的处理最终让人能看到这个物体。

随着计算机的发展,现在可以在计算机中模拟实现这种光照和反射的效果,在SVG中也有对应的实现。下面将逐一介绍SVG中模拟光照的这些滤镜。

用 SVG 模拟光

SVG中是如何实现对光的模拟的,确实比较复杂,可以查看W3C给出的SVG文档。如何实现的本文将不过多赘述,如果有感兴趣的可自行了解。这里给出文档链接。feSpecularLightingfeDiffuseLighting

本文将着重介绍在SVG中光源滤镜的使用,会先介绍基本的使用,再逐一介绍每个滤镜的属性。

介绍的滤镜分类如下

光照反射滤镜:

  • feDiffuseLighting 漫反射滤镜
  • feSpecularLighting 镜面反射滤镜

光源滤镜:

  • fePointLight 点光源
  • feDistantLight 距离光源
  • feSpotLight 聚光灯光源

如何定义

定义一个光照滤镜,需要指定以下几个因素

  1. 被照射的几何物体
  2. 光照反射类型
  3. 光的颜色
  4. 光照源

被照射的几何物体的确认是在指定滤镜的时候通过光照反射滤镜指定 in 属性传入 SourceGraphic来确认的。光照反射类型就是所用的光照反射滤镜,光的颜色通过定义光照反射滤镜lighting-color属性,光源需要在光照反射滤镜内定义光源滤镜

这里只是定义了光照,如果需要作用于物体上的效果。需要通过feComposite进行图形合成。

具体的使用如下

简单使用

feDiffuseLighting 漫反射滤镜

滤镜光照一个图像,使用 alpha 通道作为隆起映射。结果图像,是一个 RGBA 不透明图像,取决于光的颜色、光的位置以及输入隆起映射的表面几何形状。

滤镜制造的光映射可以与一个纹理图像组合,使用feComposite滤镜的多重arithmetic 操作。在应用纹理图案之前合加多个光映射可以模拟多重光源。

简单使用:

    <svg width="440" height="140" xmlns="http://www.w3.org/2000/svg">

      <!-- No light is applied -->
      <text text-anchor="middle" x="60" y="22">No Light</text>
      <circle cx="60" cy="80" r="50" fill="green" />
    
      <!-- the light source is a fePointLight element -->
      <text text-anchor="middle" x="170" y="22">fePointLight</text>
      <filter id="lightMe1">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <fePointLight x="150" y="60" z="20" />
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
    
      <circle cx="170" cy="80" r="50" fill="green" filter="url(#lightMe1)" />
    
      <!-- the light source is a feDistantLight element -->
      <text text-anchor="middle" x="280" y="22">feDistantLight</text>
      <filter id="lightMe2">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight azimuth="240" elevation="20"/>
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
    
      <circle cx="280" cy="80" r="50" fill="green" filter="url(#lightMe2)" />
    
      <!-- the light source is a feSpotLight source -->
      <text text-anchor="middle" x="390" y="22">feSpotLight</text>
      <filter id="lightMe3">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="360" y="5" z="30" limitingConeAngle="20"
                       pointsAtX="390" pointsAtY="80" pointsAtZ="0"/>
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
    
      <circle cx="390" cy="80" r="50" fill="green" filter="url(#lightMe3)" />
    </svg>
复制代码

效果如下:

image.png

feSpecularLighting 镜面反射滤镜

该滤镜照亮一个源图形,使用 alpha 通道作为隆起映射。该结果图像是一个基于光色的 RGBA 图象。该光照计算遵守标准冯氏照明模式的镜面组件。结果图像依赖于光色、光的位置以及输入隆起映射的表面几何形状。光照计算的结果是叠加的。该滤镜假定观察者在 X 方向无穷远处。

该滤镜制作了一个图像,图像包含光照计算的镜面反射部分。如此一个映射是为了与纹理相结合,使用算术feComposite方法的叠加。利用在应用到纹理图像前添加多个光映射,可以模拟多个光源。

    <svg width="440" height="140" xmlns="http://www.w3.org/2000/svg">

      <!-- No light is applied -->
      <text text-anchor="middle" x="60" y="22">No Light</text>
      <circle cx="60" cy="80" r="50" fill="green" />
    
      <!-- the light source is a fePointLight element -->
      <text text-anchor="middle" x="170" y="22">fePointLight</text>
      <filter id="lightMe1">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <fePointLight x="150" y="60" z="20" />
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
    
      <circle cx="170" cy="80" r="50" fill="green" filter="url(#lightMe1)" />
    
      <!-- the light source is a feDistantLight element -->
      <text text-anchor="middle" x="280" y="22">feDistantLight</text>
      <filter id="lightMe2">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight azimuth="240" elevation="20"/>
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
    
      <circle cx="280" cy="80" r="50" fill="green" filter="url(#lightMe2)" />
    
      <!-- the light source is a feSpotLight source -->
      <text text-anchor="middle" x="390" y="22">feSpotLight</text>
      <filter id="lightMe3">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="360" y="5" z="30" limitingConeAngle="20"
                       pointsAtX="390" pointsAtY="80" pointsAtZ="0"/>
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
    
      <circle cx="390" cy="80" r="50" fill="green" filter="url(#lightMe3)" />
    </svg>
复制代码

image.png

feDiffuseLighting 与 feSpecularLighting 的异同

相同点:

  1. 都是基于使用 alpha 通道作为隆起映射。说人话就是最后的纹理使用 rbga 四个通道值计算获得
  2. 光的颜色都需要通过光照滤镜的 lighting-color 属性来定义
  3. 在光照滤镜的内部定义光源,且只能容纳一个光源元素

不同点:

  1. feDiffuseLighting 的 alpha 值固定为 1
  2. feDiffuseLighting 中未被光照射到的地方呈现黑色。feSpecularLighting未被光照射到的地方呈现透明

滤镜属性

下面将着重介绍这些滤镜的专有属性,以及通过这些属性可做到的一些效果。

光照反射滤镜

surfaceScale

surfaceScale 定义图形基底的高度。可以用来控制图形与光源的距离

feSpecularLightingfeDiffuseLighting都可以使用

可填任意数字,默认值为1

例子:在不同光照滤镜下的表现

    <svg class="border" width="440" height="500" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <filter id="surfaceScale">
          <!-- 此时图形在 1 ,光源在20 距离为19 -->
          <feDiffuseLighting in="SourceGraphic" result="light" surfaceScale="1">
            <fePointLight x="50" y="100" z="20" />
          </feDiffuseLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="surfaceScale2">
          <!-- 此时图形在 15 ,光源在20 距离为5 -->
          <feDiffuseLighting in="SourceGraphic" result="light" surfaceScale="15">
            <fePointLight x="270" y="100" z="20" />
          </feDiffuseLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="surfaceScale3">
          <!-- 此时图形在 1 ,光源在20 距离为19 -->
          <feSpecularLighting in="SourceGraphic" result="light" surfaceScale="1">
            <fePointLight x="50" y="320" z="20" />
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="surfaceScale4">
          <!-- 此时图形在 15 ,光源在20 距离为5 -->
          <feSpecularLighting in="SourceGraphic" result="light" surfaceScale="15">
            <fePointLight x="270" y="320" z="20" />
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
      </defs>
      <circle cx="100" cy="120" r="100" fill="green"  filter="url(#surfaceScale)"/>
      <circle cx="320" cy="120" r="100" fill="green"  filter="url(#surfaceScale2)"/>
      <circle cx="100" cy="340" r="100" fill="green"  filter="url(#surfaceScale3)"/>
      <circle cx="320" cy="340" r="100" fill="green"  filter="url(#surfaceScale4)"/>
    </svg>
复制代码

image.png

diffuseConstant

diffuseConstant 控制漫反射强度。值越大,漫反射强度也越大,从图像结果来看,亮度越高。

feDiffuseLighting可以使用

可填任意正数,默认值为1

例子:

    <svg class="border" width="440" height="800" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <filter id="diffuseConstant">
          <feDiffuseLighting in="SourceGraphic" result="light" diffuseConstant="1">
            <fePointLight x="50" y="100" z="20" />
          </feDiffuseLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant2">
          <feDiffuseLighting in="SourceGraphic" result="light" diffuseConstant="2">
            <fePointLight x="270" y="100" z="20" />
          </feDiffuseLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant3">
          <feDiffuseLighting in="SourceGraphic" result="light" diffuseConstant="1">
            <feDistantLight azimuth="240" elevation="20"/>
          </feDiffuseLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant4">
          <feDiffuseLighting in="SourceGraphic" result="light" diffuseConstant="2">
            <feDistantLight azimuth="240" elevation="20"/>
          </feDiffuseLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant5">
          <feDiffuseLighting in="SourceGraphic" result="light" diffuseConstant="1">
            <feSpotLight x="10" y="500" z="30" limitingConeAngle="20"
                         pointsAtX="100" pointsAtY="560" pointsAtZ="0"/>
          </feDiffuseLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant6">
          <feDiffuseLighting in="SourceGraphic" result="light" diffuseConstant="2">
            <feSpotLight x="230" y="500" z="30" limitingConeAngle="20"
                         pointsAtX="320" pointsAtY="560" pointsAtZ="0"/>
          </feDiffuseLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
      </defs>
      <circle cx="100" cy="120" r="100" fill="green"  filter="url(#diffuseConstant)"/>
      <circle cx="320" cy="120" r="100" fill="green"  filter="url(#diffuseConstant2)"/>
      <circle cx="100" cy="340" r="100" fill="green"  filter="url(#diffuseConstant3)"/>
      <circle cx="320" cy="340" r="100" fill="green"  filter="url(#diffuseConstant4)"/>
      <circle cx="100" cy="560" r="100" fill="green"  filter="url(#diffuseConstant5)"/>
      <circle cx="320" cy="560" r="100" fill="green"  filter="url(#diffuseConstant6)"/>
    </svg>
复制代码

image.png

specularConstant

specularConstant 控制镜面反射率。值越高,镜面反射越明显。从图像结果来看,值越高颜色越接近原色,越低颜色越白(无论原图像和光的颜色是什么)

feSpecularLighting可以使用

可填任意正数,默认值为1

例子:

    <svg class="border" width="440" height="800" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <filter id="specularConstant" >
          <feSpecularLighting in="SourceGraphic" result="light" specularConstant="1">
            <fePointLight x="50" y="100" z="20" />
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="specularConstant2" >
          <feSpecularLighting in="SourceGraphic" result="light" specularConstant="0.8">
            <fePointLight x="270" y="100" z="20" />
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant3">
          <feSpecularLighting in="SourceGraphic" result="light" specularConstant="1" >
            <feDistantLight azimuth="240" elevation="20"/>
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant4">
          <feSpecularLighting in="SourceGraphic" result="light" specularConstant="0.8">
            <feDistantLight azimuth="240" elevation="20"/>
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant5">
          <feSpecularLighting in="SourceGraphic" result="light" specularConstant="1">
            <feSpotLight x="10" y="500" z="30" limitingConeAngle="20"
                         pointsAtX="100" pointsAtY="560" pointsAtZ="0"/>
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant6">
          <feSpecularLighting in="SourceGraphic" result="light" specularConstant="1.2">
            <feSpotLight x="230" y="500" z="30" limitingConeAngle="20"
                         pointsAtX="320" pointsAtY="560" pointsAtZ="0"/>
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
      </defs>
      <circle cx="100" cy="120" r="100" fill="green"  filter="url(#specularConstant)"/>
      <circle cx="320" cy="120" r="100" fill="green"  filter="url(#specularConstant2)"/>
      <circle cx="100" cy="340" r="100" fill="green"  filter="url(#diffuseConstant3)"/>
      <circle cx="320" cy="340" r="100" fill="green"  filter="url(#diffuseConstant4)"/>
      <circle cx="100" cy="560" r="100" fill="green"  filter="url(#diffuseConstant5)"/>
      <circle cx="320" cy="560" r="100" fill="green"  filter="url(#diffuseConstant6)"/>
    </svg>
复制代码

image.png

specularExponent

specularExponent 控制光源的焦点。从最后图像的焦点来看,值越大图形越亮。

feSpecularLighting可以使用

可填任意大于1的数,默认值为1

例子:

    <svg class="border" width="440" height="800" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <filter id="specularConstant" >
          <feSpecularLighting in="SourceGraphic" result="light" specularExponent="1">
            <fePointLight x="50" y="100" z="20" />
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="specularConstant2" >
          <feSpecularLighting in="SourceGraphic" result="light" specularExponent="2">
            <fePointLight x="270" y="100" z="20" />
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant3">
          <feSpecularLighting in="SourceGraphic" result="light" specularExponent="1" >
            <feDistantLight azimuth="240" elevation="20"/>
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant4">
          <feSpecularLighting in="SourceGraphic" result="light" specularExponent="2">
            <feDistantLight azimuth="240" elevation="20"/>
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant5">
          <feSpecularLighting in="SourceGraphic" result="light" specularExponent="1">
            <feSpotLight x="10" y="500" z="30" limitingConeAngle="20"
                         pointsAtX="100" pointsAtY="560" pointsAtZ="0"/>
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
        <filter id="diffuseConstant6">
          <feSpecularLighting in="SourceGraphic" result="light" specularExponent="2">
            <feSpotLight x="230" y="500" z="30" limitingConeAngle="20"
                         pointsAtX="320" pointsAtY="560" pointsAtZ="0"/>
          </feSpecularLighting>
          <feComposite in="SourceGraphic" in2="light"
                       operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
        </filter>
      </defs>
      <circle cx="100" cy="120" r="100" fill="green"  filter="url(#specularConstant)"/>
      <circle cx="320" cy="120" r="100" fill="green"  filter="url(#specularConstant2)"/>
      <circle cx="100" cy="340" r="100" fill="green"  filter="url(#diffuseConstant3)"/>
      <circle cx="320" cy="340" r="100" fill="green"  filter="url(#diffuseConstant4)"/>
      <circle cx="100" cy="560" r="100" fill="green"  filter="url(#diffuseConstant5)"/>
      <circle cx="320" cy="560" r="100" fill="green"  filter="url(#diffuseConstant6)"/>
    </svg>
复制代码

image.png

光源滤镜

fePointLight 点光源

属性:

  • x: 光源点的 x 坐标(默认值:0)
  • y: 光源点的 y 坐标(默认值:0)
  • z: 光源点的 z 坐标(默认值:1)

这里需要注意的一点是 z 确定了光源点在坐标系中 z 方向的值。这个值并不能代表光源点距离图形的距离。具体的距离是需要通过点光源属性 z 与光照属性 surfaceScale 计算得出。

两者之间的距离 = 点光源属性 z - 光照属性 surfaceScale

这里 z - surfaceScale 的值的大小最终决定最后光源的高度,具体的表现如下

例子:

    <svg  width="440" height="840" viewBox="0 -10 440 840">
      <filter id="lightMe1">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <fePointLight x="80" y="60" z="10" />
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe1_1">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <fePointLight x="80" y="180" z="0" />
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe1_2">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <fePointLight x="80" y="300" z="-10" />
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe1_3">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white" surfaceScale="20">
          <fePointLight x="80" y="420" z="10" />
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe1_4">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white" surfaceScale="-10">
          <fePointLight x="80" y="540" z="10" />
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      

      <filter id="lightMe2">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white" >
          <fePointLight x="190" y="60" z="10" />
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe2_1">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <fePointLight x="190" y="180" z="0" />
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe2_2">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <fePointLight x="190" y="300" z="-10" />
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe2_3">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white" surfaceScale="20">
          <fePointLight x="190" y="420" z="10" />
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe2_4">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white" surfaceScale="-10">
          <fePointLight x="190" y="540" z="10" />
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>

      <circle cx="100" cy="80" r="50" fill="green" filter="url(#lightMe1)" />
      <circle cx="100" cy="200" r="50" fill="green" filter="url(#lightMe1_1)" />
      <circle cx="100" cy="320" r="50" fill="green" filter="url(#lightMe1_2)" />
      <circle cx="100" cy="440" r="50" fill="green" filter="url(#lightMe1_3)" />
      <circle cx="100" cy="560" r="50" fill="green" filter="url(#lightMe1_3)" />

      <circle cx="210" cy="80" r="50" fill="green" filter="url(#lightMe2)" />
      <circle cx="210" cy="200" r="50" fill="green" filter="url(#lightMe2_1)" />
      <circle cx="210" cy="320" r="50" fill="green" filter="url(#lightMe2_2)" />
      <circle cx="210" cy="440" r="50" fill="green" filter="url(#lightMe2_3)" />
      <circle cx="210" cy="560" r="50" fill="green" filter="url(#lightMe2_3)" />

      <text text-anchor="middle" x="100" y="4">折射光</text>
      <text text-anchor="middle" x="210" y="4">自然光</text>
      <text text-anchor="middle" x="150" y="26">z = 10; surfaceScale默认为1; 距离为 9</text>
      <text text-anchor="middle" x="150" y="144">z = 0; surfaceScale默认为1; 距离为 -1</text>
      <text text-anchor="middle" x="150" y="264">z = -10; surfaceScale默认为1; 距离为 -11</text>
      <text text-anchor="middle" x="150" y="384">z = 10; surfaceScale = 20; 距离为 -10 </text>
      <text text-anchor="middle" x="150" y="504">z = 10; surfaceScale = -10; 距离为 0 </text>
    </svg>
复制代码

image.png

总结:

  • 距离为正值:feDiffuseLighting光照部分呈现光源色。feSpecularLighting光照部分呈现原色。
  • 距离为 0:feDiffuseLighting图形没有受到光照,全黑。feSpecularLighting图形没有受到光照,呈现原色。
  • 距离为负值:feDiffuseLighting图形没有受到光照,全黑。feSpecularLighting受到负方向光照源光照,光照部分呈现白色。

feDistantLight 距离光源

属性:

  • azimuth: 方位角(默认值:0)
  • elevation: 高度(默认值:0)

例子:azimuth与elevation

    <svg width="440" height="1440" xmlns="http://www.w3.org/2000/svg">
      <filter id="lightMe1">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight azimuth="0"/>
        </feDiffuseLighting>
      </filter>
      <filter id="lightMe1_1">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight azimuth="90"/>
        </feDiffuseLighting>
      </filter>
      <filter id="lightMe1_2">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight elevation="0"/>
        </feDiffuseLighting>
      </filter>
      <filter id="lightMe1_3">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight elevation="20"/>
        </feDiffuseLighting>
      </filter>
      <filter id="lightMe1_4">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight elevation="-20"/>
        </feDiffuseLighting>
      </filter>
      <filter id="lightMe1_5">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight azimuth="90" elevation="40"/>
        </feDiffuseLighting>
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>

      <filter id="lightMe2">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight azimuth="0"/>
        </feSpecularLighting>
      </filter>
      <filter id="lightMe2_1">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight azimuth="90"/>
        </feSpecularLighting>
      </filter>
      <filter id="lightMe2_2">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight elevation="0"/>
        </feSpecularLighting>
      </filter>
      <filter id="lightMe2_3">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight elevation="20"/>
        </feSpecularLighting>
      </filter>
      <filter id="lightMe2_4">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight elevation="-20"/>
        </feSpecularLighting>
      </filter>
      <filter id="lightMe2_5">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feDistantLight azimuth="90" elevation="40"/>
        </feSpecularLighting>
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>

      <text text-anchor="middle" x="60" y="14" fill="#FFF">折射光</text>
      <text text-anchor="middle" x="140" y="44" fill="#FFF">azimuth = 0</text>
      <circle cx="60" cy="120" r="50" fill="green" filter="url(#lightMe1)" />
      <text text-anchor="middle" x="140" y="220" fill="#FFF">azimuth = 90</text>
      <circle cx="60" cy="320" r="50" fill="green" filter="url(#lightMe1_1)" />
      <text text-anchor="middle" x="140" y="420" fill="#FFF">elevation = 0</text>
      <circle cx="60" cy="520" r="50" fill="green" filter="url(#lightMe1_2)" />
      <text text-anchor="middle" x="140" y="620" fill="#FFF">elevation = 20</text>
      <circle cx="60" cy="720" r="50" fill="green" filter="url(#lightMe1_3)" />
      <text text-anchor="middle" x="140" y="820" fill="#FFF">elevation = -20</text>
      <circle cx="60" cy="920" r="50" fill="green" filter="url(#lightMe1_4)" />
      <text text-anchor="middle" x="140" y="1020" fill="#FFF">图形合成</text>
      <circle cx="60" cy="1120" r="50" fill="green" filter="url(#lightMe1_5)" />

      <text text-anchor="middle" x="260" y="14" fill="#FFF">自然光</text>
      <text text-anchor="middle" x="140" y="44" fill="#FFF">azimuth = 0</text>
      <circle cx="260" cy="120" r="50" fill="green" filter="url(#lightMe2)" />
      <text text-anchor="middle" x="140" y="220" fill="#FFF">azimuth = 90</text>
      <circle cx="260" cy="320" r="50" fill="green" filter="url(#lightMe2_1)" />
      <text text-anchor="middle" x="140" y="420" fill="#FFF">elevation = 0</text>
      <circle cx="260" cy="520" r="50" fill="green" filter="url(#lightMe2_2)" />
      <text text-anchor="middle" x="140" y="620" fill="#FFF">elevation = 20</text>
      <circle cx="260" cy="720" r="50" fill="green" filter="url(#lightMe2_3)" />
      <text text-anchor="middle" x="140" y="820" fill="#FFF">elevation = -20</text>
      <circle cx="260" cy="920" r="50" fill="green" filter="url(#lightMe2_4)" />
      <text text-anchor="middle" x="140" y="1020" fill="#FFF">图形合成</text>
      <circle cx="260" cy="1120" r="50" fill="green" filter="url(#lightMe2_5)" />
    </svg>
复制代码

image.png

feSpotLight 聚光灯光源

  • x: 光源点的 x 坐标(默认值:0)
  • y: 光源点的 y 坐标(默认值:0)
  • z: 光源点的 z 坐标(默认值:1)
  • pointsAtX: 光源照射点的 x 坐标 (默认值:0)
  • pointsAtY: 光源照射点的 y 坐标 (默认值:0)
  • pointsAtZ: 光源照射点的 z 坐标 (默认值:0)
  • specularExponent: 控制光源的焦点, 光照边界越模糊(默认值:1)。表现为:feDiffuseLighting 内,值越大,图像越暗。feSpecularLighting内,值越大,图像越亮。
  • limitingConeAngle:光的投射角,值越大,光照范围越大(默认值:0)

例子:

    <h4>红色点为光源点</h4>
    <svg width="240" height="640" xmlns="http://www.w3.org/2000/svg">
      <filter id="lightMe1">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="80" y="5" z="30" limitingConeAngle="20" specularExponent="5" pointsAtX="60" pointsAtY="80" pointsAtZ="00"/>
        </feDiffuseLighting>
        <feComposite in="SourceGraphic" in2="light" operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe1_1">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="80" y="145" z="30" limitingConeAngle="25" specularExponent="5" pointsAtX="60" pointsAtY="220" pointsAtZ="00"/>
        </feDiffuseLighting>
        <feComposite in="SourceGraphic" in2="light" operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe1_2">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="80" y="285" z="30" limitingConeAngle="20" specularExponent="30" pointsAtX="60" pointsAtY="360" pointsAtZ="00"/>
        </feDiffuseLighting>
        <feComposite in="SourceGraphic" in2="light" operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>

      <filter id="lightMe2">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="140" y="5" z="30" limitingConeAngle="20" specularExponent="5" pointsAtX="170" pointsAtY="80" pointsAtZ="0"/>
        </feSpecularLighting>
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe2_1">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="140" y="145" z="30" limitingConeAngle="25" specularExponent="5" pointsAtX="170" pointsAtY="220" pointsAtZ="0"/>
        </feSpecularLighting>
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <filter id="lightMe2_2">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="140" y="285" z="30" limitingConeAngle="20" specularExponent="30" pointsAtX="170" pointsAtY="360" pointsAtZ="0"/>
        </feSpecularLighting>
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>

      <text text-anchor="middle" x="60" y="14">折射光</text>
      <circle cx="60" cy="80" r="50" fill="green" filter="url(#lightMe1)" />
      <circle cx="80" cy="5" r="2" fill="red"  />
      <circle cx="60" cy="220" r="50" fill="green" filter="url(#lightMe1_1)"/>
      <circle cx="80" cy="145" r="2" fill="red"  />
      <circle cx="60" cy="360" r="50" fill="green" filter="url(#lightMe1_2)" />
      <circle cx="80" cy="285" r="2" fill="red"  />

      <text text-anchor="middle" x="170" y="14">自然光</text>
      <circle cx="170" cy="80" r="50" fill="green" filter="url(#lightMe2)" />
      <circle cx="140" cy="5" r="2" fill="red"  />
      <circle cx="170" cy="220" r="50" fill="green" filter="url(#lightMe2_1)"/>
      <circle cx="140" cy="145" r="2" fill="red"  />
      <circle cx="170" cy="360" r="50" fill="green" filter="url(#lightMe2_2)" />
      <circle cx="140" cy="285" r="2" fill="red"  />
    </svg>
复制代码

image.png

光照滤镜的应用

通过光照给图像不同的颜色

我买可以通过光照滤镜,来给白色的图形或者图片,动态变换不同的颜色。

这里采用的是feDiffuseLighting + feSpotLight 来实现的

例子:让白色的圆变成绿色

    <svg width="200" height="640">
      <filter id="lightColor">
        <!-- 这里surfaceScale必须要要为0,不然会有黑边。surfaceScale的默认值是 1 -->
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="green" surfaceScale="0">
          <!-- specularExponent 最好也为0。这样边界的模糊不明显 -->
          <feSpotLight x="60" y="100" z="1000" limitingConeAngle="20" specularExponent="0" pointsAtX="60" pointsAtY="100" pointsAtZ="0"/>
        </feDiffuseLighting>
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <text text-anchor="middle" x="60" y="54">绿色的圆</text>
      <circle cx="60" cy="120" r="50" fill="green" />
      <text text-anchor="middle" x="80" y="194">白色的圆照绿色的光</text>
      <circle cx="60" cy="260" r="50" fill="#FFFFFF" filter="url(#lightColor)"/>
    </svg>
复制代码

image.png

这时有人可能就要问了,直接设置fill属性不就好了吧,干嘛要多此一举。

因为它最重要的一个特点是,滤镜可作用于图片。只要是白色图形的图片都可以利用滤镜来更换颜色。非常好用。

特别的,如果图片有不透明度的颜色区域,光照滤镜也能很好的表现出来。

例子:将png图片变换颜色

    <svg width="200" height="640">
      <filter id="lightColor">
        <!-- 这里surfaceScale必须要要为0,不然会有黑边。surfaceScale的默认值是 1 -->
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="green" surfaceScale="0">
          <!-- specularExponent 最好也为0。这样边界的模糊不明显 -->
          <feSpotLight x="60" y="100" z="1000" limitingConeAngle="20" specularExponent="0" pointsAtX="60" pointsAtY="100" pointsAtZ="0"/>
        </feDiffuseLighting>
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <image href="/static/image/V.png" x="0" y="0" height="100" width="100" filter="url(#lightColor)"></image>
      <!-- 特别的,如果图片有不透明度的颜色区域,光照滤镜也能很好的表现出来 -->
      <image href="/static/image/firewall.png" x="0" y="140" height="65" width="70" filter="url(#lightColor)"></image>
    </svg>
复制代码

image.png

制作闪烁效果

在上一个应用的基础上添加动画,我们就能得到一个类似闪烁的效果。

    <svg width="200" height="640">
      <filter id="twinkle">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="#FFFFFF" surfaceScale="0">
          <animate attributeName="lighting-color" values="#FFFFFF;#FF8000;#FFFFFF" dur="2s" repeatCount="indefinite" />
          <feSpotLight x="60" y="100" z="1000" limitingConeAngle="20" specularExponent="0" pointsAtX="60" pointsAtY="100" pointsAtZ="0"/>
        </feDiffuseLighting>
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <image href="/static/image/V.png" x="0" y="0" height="100" width="100" filter="url(#twinkle)"></image>
      <!-- 特别的,如果图片有不透明度的颜色区域,光照滤镜也能很好的表现出来 -->
      <image href="/static/image/firewall.png" x="0" y="140" height="65" width="70" filter="url(#twinkle)"></image>
    </svg>
复制代码

twinkle.gif

聚光灯入场效果

同样的,也是feSpotLight的应用。通过控制照射点及投射角度来模拟聚光灯入场的效果。

    <svg width="440" height="640" xmlns="http://www.w3.org/2000/svg">
      <filter id="lightMe3">
        <feDiffuseLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="170" y="180" z="150" limitingConeAngle="20" pointsAtX="170" pointsAtY="180" pointsAtZ="0">
            <animate attributeName="pointsAtX" values="0;300;170;170" dur="4s" repeatCount="indefinite" />
            <animate attributeName="z" values="150;150;150;220" dur="4s" repeatCount="indefinite" />
          </feSpotLight>
        </feDiffuseLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>

      <filter id="lightMe4">
        <feSpecularLighting in="SourceGraphic" result="light" lighting-color="white">
          <feSpotLight x="170" y="430" z="150" limitingConeAngle="20" pointsAtX="170" pointsAtY="430" pointsAtZ="0">
            <animate attributeName="pointsAtX" values="0;300;170;170" dur="4s" repeatCount="indefinite" />
            <animate attributeName="z" values="150;150;150;220" dur="4s" repeatCount="indefinite" />
          </feSpotLight>
        </feSpecularLighting>
    
        <feComposite in="SourceGraphic" in2="light"
                     operator="arithmetic" k1="1" k2="0" k3="0" k4="0"/>
      </filter>
      <text text-anchor="middle" x="120" y="64">可以做一个聚光灯的特效</text>
      <g filter="url(#lightMe3)" >
        <circle cx="170" cy="180" r="100" fill="green"  />
        <image width="100" height="100" x="120" y="130" href="../../../image/VIP.png"></image>
      </g>
      <circle cx="170" cy="280" r="2" fill="red"  />
      <text text-anchor="middle" x="120" y="314">同理使用自然光的效果如下</text>
      <g filter="url(#lightMe4)">
        <circle cx="170" cy="430" r="100" fill="green"  />
        <image width="100" height="100" x="120" y="380" href="../../../image/VIP.png"></image>
      </g>
      <circle cx="170" cy="430" r="2" fill="red"  />
    </svg>
复制代码

lightMe.gif

最后

文章中如果有什么不对的地方,欢迎在评论区里指正。

参考资料

参考来源 - MDN

往期文章

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

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

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

猜你喜欢

转载自juejin.im/post/7132306133162655781
SVG
今日推荐