如何为SVG中矩形及叠放在其上方的圆形分别添加投影效果
问题场景
- 现有一个矩形,其左侧叠放一个圆形,两个图形填充均为白色。
- 目标效果:为矩形添加适配的投影,同时为叠放在矩形左上方的圆形添加对应投影,实现符合层级逻辑的视觉效果。
- 当前进度:已编写两套分别匹配矩形、圆形投影参数的SVG滤镜,两个元素上的滤镜调用代码目前处于注释状态,未生效。
初始实现代码如下:
let svg = d3.select("#container") .append("svg"); svg.select("defs") .append("svg:filter") .attr("id", "nodeShadow") .append("feDropShadow") .attr("dx", 0.5) .attr("dy", 3.2) .attr("stdDeviation", 3) .attr("flood-opacity", 0.3) .attr("flood-color", "lightgray"); svg.select("defs") .append("svg:filter") .attr("id", "circleShadow") .append("feDropShadow") .attr("dx", 2.0) .attr("dy", 1.6) .attr("stdDeviation", 4) .attr("flood-color", "lightgray"); // node let containerNode = svg.append("g"); containerNode.append("rect") .attr("x", 100) .attr("y", 150) //.attr("filter", "url(#nodeShadow)") .attr("fill", "#FFFFFF") .attr("width", 250) .attr("height", 30); containerNode.append("circle") .attr("cx", 115) .attr("cy", 165) .attr("r", 15) .attr("fill", "transparent") //.attr("filter", "url(#circleShadow)") .attr("stroke", "#ffffff") .attr("stroke-width", "0.001") .attr("width", 30) .attr("height", 30);
解决方案
按以下三点调整即可实现正确的分层投影:
- 修正圆形填充属性:将圆形的
fill值从transparent改为#FFFFFF,和矩形填充保持一致。透明填充的元素应用投影时,仅宽度0.001的描边会生成投影,视觉上几乎不可见,无法达到预期效果。 - 扩大滤镜渲染区域:给两个滤镜节点添加
x/y/width/height属性,预留足够的投影绘制空间,避免投影边缘被滤镜默认边界裁切。 - 按层级应用滤镜:SVG遵循「后绘制元素层级更高」的规则,保持现有先画矩形、后画圆形的顺序,直接取消两个元素上的滤镜注释即可。最终效果为矩形投影落在页面背景上,圆形投影自然落在下层的矩形表面,完全符合真实叠放的视觉逻辑。
修正后核心代码
let svg = d3.select("#container") .append("svg"); // 配置矩形滤镜,预留投影空间避免裁切 svg.select("defs") .append("svg:filter") .attr("id", "nodeShadow") .attr("x", "-20%") .attr("y", "-20%") .attr("width", "140%") .attr("height", "140%") .append("feDropShadow") .attr("dx", 0.5) .attr("dy", 3.2) .attr("stdDeviation", 3) .attr("flood-opacity", 0.3) .attr("flood-color", "lightgray"); // 配置圆形滤镜,预留投影空间避免裁切 svg.select("defs") .append("svg:filter") .attr("id", "circleShadow") .attr("x", "-50%") .attr("y", "-50%") .attr("width", "200%") .attr("height", "200%") .append("feDropShadow") .attr("dx", 2.0) .attr("dy", 1.6) .attr("stdDeviation", 4) .attr("flood-opacity", 0.3) .attr("flood-color", "lightgray"); // 绘制节点组 let containerNode = svg.append("g"); // 绘制矩形,应用矩形投影 containerNode.append("rect") .attr("x", 100) .attr("y", 150) .attr("filter", "url(#nodeShadow)") .attr("fill", "#FFFFFF") .attr("width", 250) .attr("height", 30); // 绘制圆形,应用圆形投影 containerNode.append("circle") .attr("cx", 115) .attr("cy", 165) .attr("r", 15) .attr("fill", "#FFFFFF") .attr("filter", "url(#circleShadow)") .attr("stroke", "#ffffff") .attr("stroke-width", "0.001");
内容的提问来源于stack exchange,提问作者Ace
相关产品推荐
相关产品推荐

