feSpecularLighting 用于模拟镜面反射光照.
他的核心属性如下:
in:输入图像surfaceScale:峰值高度, 默认值为 1, 取值范围为 0 到 100. 值越大, 阴影和高光越强烈, 起伏感越强lighting-color:光源颜色, 默认值为 whitespecularExponent:镜面反射系数, 控制高光的聚集程度(光斑大小), 值越小, 光斑越扩散, 值越大, 光斑越锐利、越小, 例如抛光金属或者玻璃specularConstant:镜面常数, 控制高光的强度/亮度, 值越大, 反光越刺眼这是最基础的用法. 我们将一个扁平的圆形, 通过添加高光, 瞬间变成具有 Q 弹质感的果冻按钮.
01export default function App() {02return (03<div className="w-full h-full flex flex-col items-center justify-center rounded-xl p-8 relative overflow-hidden">04<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">05<defs>06<filter id="demo1-specular-lighting">07{/* 1. 模糊 Alpha, 制造圆润的斜坡 */}08<feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" />0910{/* 2. 生成高光层 */}11{/* specularExponent="25": 适中的光斑, 看起来像软塑料或凝胶 */}12{/* lighting-color: 白色高光 */}13<feSpecularLighting14in="blur"15surfaceScale={5}16specularConstant={1}17specularExponent={25}18lightingColor="white"19result="specularOut"20>21<fePointLight x={50} y={50} z={60} />22</feSpecularLighting>2324{/* 3. 关键步骤:合成 */}25{/* 将高光层 (specularOut) 叠加在原始图形 (SourceGraphic) 上 */}26{/* arithmetic k2="1" k3="1" 相当于简单的相加 (Add) */}27<feComposite28in="SourceGraphic"29in2="specularOut"30operator="arithmetic"31k1={0}32k2={1}33k3={1}34k4={0}35/>36</filter>37</defs>3839{/* 原始图形:一个粉色的圆 */}40<circle cx={100} cy={100} r={60} fill="#ff4081" filter="url(#demo1-specular-lighting)" />41</svg>42</div>43);44}45
这个案例, 我们使用 feSpecularLighting 来模拟一个金属质感.
金属感的秘诀在于反差. feDiffuseLighting 提供了灰暗的基调, 而 feSpecularLighting (exponent=80) 提供了那一道像刀锋一样锐利的白光.
01export default function App() {02return (03<div className="w-full h-full flex flex-col items-center justify-center rounded-xl p-8 relative overflow-hidden">04<svg width="400" height="150" viewBox="0 0 400 150" xmlns="http://www.w3.org/2000/svg">05<defs>06<filter id="demo2-specular-lighting">07{/* 1. 模糊源图像 Alpha */}08<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur" />0910{/* 2. 制造暗部/体积感 (Diffuse) */}11{/* lightingColor="#666" 是个技巧, 用它来压暗边缘, 或者用深灰色 */}12<feDiffuseLighting13in="blur"14surfaceScale={4}15lightingColor="#666"16result="diffuseOut"17>18<feDistantLight azimuth={45} elevation={60} />19</feDiffuseLighting>2021{/* 3. 制造锐利高光 (Specular) */}22{/* specularExponent="80": 非常高, 模拟抛光金属的锐利反光 */}23<feSpecularLighting24in="blur"25surfaceScale={6}26specularConstant={1.5}27specularExponent={80}28lightingColor="#fff"29result="specularOut"30>31<feDistantLight azimuth={45} elevation={60} />32</feSpecularLighting>3334{/* 4. 复杂的合成链 */}35{/* 先把 Diffuse 叠到底色上 */}36<feComposite37in="diffuseOut"38in2="SourceGraphic"39operator="arithmetic"40k1={1}41k2={0}42k3={0}43k4={0}44result="shaded"45/>4647{/* 再把 Specular 加到结果上 */}48<feComposite49in="specularOut"50in2="shaded"51operator="arithmetic"52k2={1}53k3={1}54result="metallic"55/>5657{/* 最后裁切掉文字外部 */}58<feComposite59in="metallic"60in2="SourceAlpha"61operator="in"62/>63</filter>64</defs>6566<text67x="50%"68y="60%"69textAnchor="middle"70fontFamily="Impact"71fontSize="80"72fill="#aaa"73filter="url(#demo2-specular-lighting)"74>75METAL76</text>77</svg>78</div>79);80}81
这个案例, 我们使用 feSpecularLighting 来模拟一个动态扫描光.
SVG 滤镜最酷的地方在于它的属性是可以动画化的. 我们可以让 <fePointLight> 的坐标移动, 模拟黑夜中探照灯扫过物体的效果. 这非常适合做 Loading 动画或 Logo 展示.
01export default function App() {02return (03<div className="w-full h-full flex flex-col items-center bg-gray-900 justify-center rounded-xl p-8 relative overflow-hidden">04<svg width="300" height="150" viewBox="0 0 300 150" xmlns="http://www.w3.org/2000/svg">05<defs>06<filter id="moving-light" x="-50%" y="-50%" width="200%" height="200%">07{/* 1. 准备高度图 */}08<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur" />0910{/* 2. 动态光照 */}11{/* specularExponent=35: 聚光效果明显 */}12<feSpecularLighting13in="blur"14surfaceScale="5"15specularConstant="2"16specularExponent="35"17lightingColor="#ff0055"18result="light"19>20{/* 点光源 */}21<fePointLight x="-50" y="75" z="30">22{/* 动画:让光从左扫到右 */}23<animate attributeName="x" from="-50" to="350" dur="3s" repeatCount="indefinite" />24</fePointLight>25</feSpecularLighting>2627{/* 3. 合成 */}28{/* 我们把原始图形设为暗色, 只在有光划过时变亮 */}29{/* 使用 arithmetic 将光照叠加在原图上 */}30<feComposite31in="light"32in2="SourceGraphic"33operator="arithmetic"34k1="0"35k2="0.2"36k3="1"37k4="0"38/>39</filter>40</defs>4142{/* 文字本身是深灰色的, 只有光照扫过才会亮起洋红色 */}43<text44x="50%"45y="50%"46dy=".3em"47textAnchor="middle"48fontFamily="Verdana"49fontWeight="900"50fontSize="60"51fill="#333"52filter="url(#moving-light)"53>54usehook55</text>56</svg>57</div>58);59}60
这个案例, 我们使用 feSpecularLighting 来模拟一个水滴高光.
fill-opacity="0.1").<feSpecularLighting> 生成的那个白色亮斑, 以及 <feDropShadow> 生成的阴影构成的.01export default function App() {02return (03<div className="w-full h-full flex flex-col items-center bg-gray-800 justify-center rounded-xl p-8 relative overflow-hidden">04<svg width="300" height="200" viewBox="0 0 300 200" xmlns="http://www.w3.org/2000/svg">05<defs>06<filter id="water-drops">07{/* 1. 模糊源, 制造水滴的弧度 */}08<feGaussianBlur in="SourceAlpha" stdDeviation="6" result="blur" />0910{/* 2. 生成高光 */}11{/* 高 surfaceScale (15) 模拟水滴的高突起 */}12{/* exponent=40 模拟湿润的表面 */}13<feSpecularLighting14in="blur"15surfaceScale={15}16specularConstant={2.5}17specularExponent={40}18lightingColor="#fff"19result="specular"20>21<fePointLight x={50} y={50} z={100} />22</feSpecularLighting>2324{/* 3. 合成:只显示高光 + 原始的一点点透明度 */}25{/* 这里的关键是我们几乎丢弃了 SourceGraphic 的颜色, 主要保留高光 */}26<feComposite in="specular" in2="SourceGraphic" operator="in" result="glint" />2728{/* 4. 给水滴加一点阴影让它更立体 (可选) */}29<feDropShadow dx={2} dy={4} stdDeviation={3} floodOpacity={0.3} />30</filter>31</defs>3233<rect width="100%" height="100%" fill="url(#bg)" />3435{/* 水滴组 */}36{/* 颜色 fillOpacity 设为 0.1, 因为水是透明的 */}37<g filter="url(#water-drops)" fill="white" fillOpacity={0.1}>38<circle cx={100} cy={80} r={30} />39<circle cx={180} cy={120} r={40} />40<path41d="M50,150 Q80,120 110,150 T170,150"42stroke="white"43strokeWidth={20}44strokeLinecap="round"45fill="none"46/>47</g>48</svg>49</div>50);51}52