如何使用D3防止小形状的前卫阴影

时间:2014-03-27 10:18:47

标签: graphics d3.js shadow dropshadow svg-filters

我正在开发一个小型教育工具,我想为SVG路径添加阴影。要构建我的图形,我使用D3.js.这通常很有效,但是在特定的形状下我会遇到问题,特别是对于有水平和/或垂直线条的小形状。

为了说明这一点,我制作了一个带有三个三角形的JSFiddle example。绿色三角形上的阴影看起来很漂亮,橙色三角形上的阴影仍然很好,但红色三角形上的阴影看起来非常难看。

使用this code创建阴影作为示例:

var defs = svg.append("defs").attr("height","160%");
var filter = defs.append("filter").attr("id", "schaduw");
filter.append("feGaussianBlur").attr("in", "SourceAlpha")
      .attr("stdDeviation", 5).attr("result", "blur");
filter.append("feOffset").attr("in", "blur")
      .attr("dx", 3)
      .attr("dy", 3)
      .attr("result", "offsetBlur");
var feMerge = filter.append("feMerge");
feMerge.append("feMergeNode").attr("in", "offsetBlur");
feMerge.append("feMergeNode").attr("in", "SourceGraphic");

从JSFiddle代码中可以看出,形状之间唯一有意义的区别是它们的大小。如何防止小形状出现难看的阴影?

非常感谢任何帮助! =)

2 个答案:

答案 0 :(得分:1)

您的阴影正被基础SVG过滤器的过滤器区域剪切。默认情况下,滤镜效果显示在滤镜形状周围的10%溢出区域中。你在较小的形状上的阴影太大,并溢出该区域。这导致了边缘。您需要添加一个显式过滤器区域并使其更大。这会将滤镜区域扩展到形状周围的20%区域:

var filter = defs.append("filter").attr("id", "schaduw") .attr("width", 1.4) 
    .attr("height",1.4) .attr("x",-0.2) .attr("y",-0.2);

如果你想要一个与过滤元素成比例的阴影,你不需要计算任何东西的大小。 SVG具有通过在objectBoundingBox单元中定义单位来进行相对大小调整的内置功能。在这里,您应该使用objectBoundingBox单位作为过滤器基本单位,而不是userSpaceUnits(“常规”视图框单位)的(静默)默认值。您需要重新设置模糊的stdDeviation,以及以小数表示的原始元素框%的偏移量偏移量:

var filter = defs.append("filter").attr("id", "schaduw") .attr("width", 1.4) 
     .attr("height",1.4) .attr("x",-0.2) .attr("y",-0.2)     
     .attr("primitiveUnits","objectBoundingBox");
filter.append("feGaussianBlur").attr("in", "SourceAlpha")
              .attr("stdDeviation", .02).attr("result", "blur");
filter.append("feOffset").attr("in", "blur")
              .attr("dx", .01)
              .attr("dy", .01)
              .attr("result", "offsetBlur");
var feMerge = filter.append("feMerge");
feMerge.append("feMergeNode").attr("in", "offsetBlur");
feMerge.append("feMergeNode").attr("in", "SourceGraphic");

现在,您会注意到这看起来有点奇怪 - 因为只要您希望所有形状看起来都在同一个平面上,无论多小或多大,您的投影大小应该在各个形状上保持一致他们是。

答案 1 :(得分:0)

您所引用的阴影质量由您使用的高斯模糊的标准偏差控制。使用绝对值意味着阴影是"展开"无论您使用过滤器的元素大小,都是相同的数量。对于较小的形状,这会产生您所看到的效果。

有两种方法可以解决这个问题。快速简便的方法是降低标准偏差,使其即使对于最小的形状也看起来很好。我已通过设置.attr("stdDeviation", 1)在您的示例here中完成此操作。

另一个选择是针对不同的形状尺寸设置不同的标准偏差,因为我已经以hacky的方式完成了here。这将更加困难,因为它需要您计算形状的大小,确定合适的标准偏差,并且如果它不存在则可能创建适当的过滤器。此外,阴影看起来不那么一致。