前言
本篇文章将介绍SVG
的光源滤镜。包括: 用来描述光源反射方式的feDiffuseLighting
和 feSpecularLighting
,以及用来描述光源的 fePointLight
、feDistantLight
、feSpotLight
。并且将会通过一些实际的使用案例来详细说明。
人为什么能看到光
首先,在介绍和使用这些滤镜的时候,我们需要明白一个原理。人为什么能够看到东西?
在现实生活中,太阳发出的光照射到物体上,被照射的物体会吸收一部分光,并将剩余的光反射出去。人的眼睛接受到物体反射来的光,经过大脑的处理最终让人能看到这个物体。
随着计算机的发展,现在可以在计算机中模拟实现这种光照和反射的效果,在SVG中也有对应的实现。下面将逐一介绍SVG
中模拟光照的这些滤镜。
用 SVG 模拟光
SVG
中是如何实现对光的模拟的,确实比较复杂,可以查看W3C
给出的SVG
文档。如何实现的本文将不过多赘述,如果有感兴趣的可自行了解。这里给出文档链接。feSpecularLighting和feDiffuseLighting
本文将着重介绍在SVG
中光源滤镜的使用,会先介绍基本的使用,再逐一介绍每个滤镜的属性。
介绍的滤镜分类如下
光照反射滤镜:
- feDiffuseLighting 漫反射滤镜
- feSpecularLighting 镜面反射滤镜
光源滤镜:
- fePointLight 点光源
- feDistantLight 距离光源
- feSpotLight 聚光灯光源
如何定义
定义一个光照滤镜,需要指定以下几个因素
- 被照射的几何物体
- 光照反射类型
- 光的颜色
- 光照源
被照射的几何物体的确认是在指定滤镜的时候通过光照反射滤镜
指定 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>
复制代码
效果如下:
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>
复制代码
feDiffuseLighting 与 feSpecularLighting 的异同
相同点:
- 都是基于使用 alpha 通道作为隆起映射。说人话就是最后的纹理使用 rbga 四个通道值计算获得
- 光的颜色都需要通过光照滤镜的
lighting-color
属性来定义 - 在光照滤镜的内部定义光源,且只能容纳一个光源元素
不同点:
feDiffuseLighting
的 alpha 值固定为 1feDiffuseLighting
中未被光照射到的地方呈现黑色。feSpecularLighting
未被光照射到的地方呈现透明
滤镜属性
下面将着重介绍这些滤镜的专有属性,以及通过这些属性可做到的一些效果。
光照反射滤镜
surfaceScale
surfaceScale 定义图形基底的高度。可以用来控制图形与光源的距离
feSpecularLighting
和feDiffuseLighting
都可以使用
可填任意数字,默认值为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>
复制代码
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>
复制代码
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>
复制代码
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>
复制代码
光源滤镜
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>
复制代码
总结:
- 距离为正值:
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>
复制代码
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>
复制代码
光照滤镜的应用
通过光照给图像不同的颜色
我买可以通过光照滤镜,来给白色的图形或者图片,动态变换不同的颜色。
这里采用的是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>
复制代码
这时有人可能就要问了,直接设置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>
复制代码
制作闪烁效果
在上一个应用的基础上添加动画,我们就能得到一个类似闪烁的效果。
<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>
复制代码
聚光灯入场效果
同样的,也是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>
复制代码
最后
文章中如果有什么不对的地方,欢迎在评论区里指正。
参考资料
往期文章