feSpecularLighting 用于模拟镜面反射光照。
他的核心属性如下:
in:输入图像surfaceScale:峰值高度,默认值为 1,取值范围为 0 到 100。值越大,阴影和高光越强烈,起伏感越强lighting-color:光源颜色,默认值为 whitespecularExponent:镜面反射系数,控制高光的聚集程度(光斑大小),值越小,光斑越扩散,值越大,光斑越锐利、越小,例如抛光金属或者玻璃specularConstant:镜面常数,控制高光的强度/亮度,值越大,反光越刺眼这是最基础的用法。我们将一个扁平的圆形,通过添加高光,瞬间变成具有 Q 弹质感的果冻按钮。
10export default function App() {20return (30<div className="w-full h-full flex flex-col items-center justify-center rounded-xl p-8 relative overflow-hidden">40<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">50<defs>60<filter id="demo1-specular-lighting">70{/* 1. 模糊 Alpha,制造圆润的斜坡 */}80<feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" />9010{/* 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) 提供了那一道像刀锋一样锐利的白光。
10export default function App() {20return (30<div className="w-full h-full flex flex-col items-center justify-center rounded-xl p-8 relative overflow-hidden">40<svg width="400" height="150" viewBox="0 0 400 150" xmlns="http://www.w3.org/2000/svg">50<defs>60<filter id="demo2-specular-lighting">70{/* 1. 模糊源图像 Alpha */}80<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur" />9010{/* 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 展示。
10export default function App() {20return (30<div className="w-full h-full flex flex-col items-center bg-gray-900 justify-center rounded-xl p-8 relative overflow-hidden">40<svg width="300" height="150" viewBox="0 0 300 150" xmlns="http://www.w3.org/2000/svg">50<defs>60<filter id="moving-light" x="-50%" y="-50%" width="200%" height="200%">70{/* 1. 准备高度图 */}80<feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur" />9010{/* 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> 生成的阴影构成的。10export default function App() {20return (30<div className="w-full h-full flex flex-col items-center bg-gray-800 justify-center rounded-xl p-8 relative overflow-hidden">40<svg width="300" height="200" viewBox="0 0 300 200" xmlns="http://www.w3.org/2000/svg">50<defs>60<filter id="water-drops">70{/* 1. 模糊源,制造水滴的弧度 */}80<feGaussianBlur in="SourceAlpha" stdDeviation="6" result="blur" />9010{/* 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