使用filters和d3.js在svg中部分更改阴影不透明度

时间:2018-06-03 20:10:01

标签: javascript d3.js svg svg-filters

如何使用filters和d3.js在svg中部分更改阴影不透明度?

这就是我希望我的阴影看起来像: enter image description here

我的意思是由写入Entity Name的矩形删除的阴影。

这是我迄今为止所取得的成就:

var svg = d3.select("#drawRegion")
                .append("svg")
                .attr("width", "100%")
                .attr("height", "100%");
                
                
var defs = svg.append("defs");

var filter = defs.append("filter")
                 		.attr("id","coolShadow");

filter.append("feMorphology")
  .attr("in", "SourceGraphic")
  .attr("result", "upperLayer")
  .attr("operator", "dilate")
  .attr("radius", "2 2");

filter.append("feMorphology")
  .attr("in", "SourceAlpha")
  .attr("result", "enlargedAlpha")
  .attr("operator", "dilate")
  .attr("radius", "3 5");

filter.append("feGaussianBlur")
  .attr("in", "enlargedAlpha")
  .attr("result", "bluredAlpha")
  .attr("stdDeviation", "5");
  
filter.append("feOffset")
  .attr("in", "bluredAlpha")
  .attr("result", "lowerLayer")
  .attr("dy", "3");


var feMerge = filter.append("feMerge");
feMerge.append("feMergeNode")
  .attr("in","lowerLayer");
feMerge.append("feMergeNode")
  .attr("in","upperLayer");

svg.append("rect")
    .attr("rx", 2)
    .attr("ry", 2)
	.attr("x", "20%")
  .attr("y", "20%")
  .attr("width", "60%")
  .attr("height", "60%")
  .attr("fill", "white")
  .style("filter", "url(#coolShadow)");
  
  
  
  
  
  
  
  
#drawRegion {
    width: 100%;
    height: 100%;
    display: inline-block;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    position: relative;
}
<div id="drawRegion">

</div>
<script src="https://d3js.org/d3.v5.min.js"></script>

你可以看到阴影几乎准备好了。唯一我无法弄清楚如何实现的 - 是增加不透明度(现在它太高了,我想降低它,但同时保留左,上,右边框的透明胶片)。

我尝试降低整体不透明度,但它没有帮助:左边,上边和右边框的透明度也减少了,而我想让下边框部分更透明并保留其他边框。

如果有任何更正可以让我解决这个问题,或者完全不同的解决方案,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

您可以使用opacitydy属性进行游戏。

不透明度将全局使阴影更亮或更暗(值介于0和1之间)。

dy属性(同样适用于dx)垂直移动阴影(“移动光源”)。

如果dy0,则阴影以形状为中心(光源位于形状上方)。如果(在你的情况下),dy是正的,那么阴影将被转换到底部,因此在阴影的形状下会更明显。

以下是opacity 0.3的示例:

.style("opacity", 0.3)

dy 0(您可以使用它来根据自己的风格进行调整):

.attr("dy", "0")

var svg = d3.select("#drawRegion")
                .append("svg")
                .attr("width", "100%")
                .attr("height", "100%");
                
                
var defs = svg.append("defs");

var filter = defs.append("filter")
                 		.attr("id","coolShadow")
                    .attr("x", "-100%").attr("y", "-100%") //
                    .attr("width", "300%").attr("height", "300%"); //

filter.append("feMorphology")
  .attr("in", "SourceGraphic")
  .attr("result", "upperLayer")
  .attr("operator", "dilate")
  .attr("radius", "2 2");

filter.append("feMorphology")
  .attr("in", "SourceAlpha")
  .attr("result", "enlargedAlpha")
  .attr("operator", "dilate")
  .attr("radius", "3 5");

filter.append("feGaussianBlur")
  .attr("in", "enlargedAlpha")
  .attr("result", "bluredAlpha")
  .attr("stdDeviation", "4");
  
filter.append("feOffset")
  .attr("in", "bluredAlpha")
  .attr("result", "lowerLayer")
  .attr("dy", "0"); //


var feMerge = filter.append("feMerge");
feMerge.append("feMergeNode")
  .attr("in","lowerLayer");
feMerge.append("feMergeNode")
  .attr("in","upperLayer");

svg.append("rect")
    .attr("rx", 2)
    .attr("ry", 2)
	.attr("x", "20%")
  .attr("y", "20%")
  .attr("width", "60%")
  .attr("height", "60%")
  .attr("fill", "white")
  .style("filter", "url(#coolShadow)")
  .style("opacity", 0.3); //
#drawRegion {
    width: 100%;
    height: 100%;
    display: inline-block;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    position: relative;
}
<div id="drawRegion">

</div>
<script src="https://d3js.org/d3.v5.min.js"></script>

注意我是如何修改应用阴影的宽度/高度/位置以避免被截断的:

var filter = defs.append("filter")
               .attr("id", "coolShadow")
               .attr("x", "-100%").attr("y", "-100%")
               .attr("width", "300%").attr("height", "300%");

答案 1 :(得分:1)

实现您想要做的事情的最佳方法是在第二个feMorphology上回拨y半径,在feOffset上回拨y。有一些方法可以有选择地实际降低不透明度,但它们会导致阴影中的不连续性 - 这可能是您不想要的。

(你还需要扩展你的过滤区域 - 我在这里为你做的)。

我想知道你为什么要使用feMorphology扩展源矩形?如果你想要一个稍微圆角的较大的矩形,你可以直接在SVG中绘制它 - 它会更高效。 feMorphology是一个缓慢的操作。

&#13;
&#13;
var svg = d3.select("#drawRegion")
                .append("svg")
                .attr("width", "100%")
                .attr("height", "100%");
                
                
var defs = svg.append("defs");

var filter = defs.append("filter")
                 		.attr("id","coolShadow")
                 		.attr("y","-20%")
                 		.attr("height","140%");

filter.append("feMorphology")
  .attr("in", "SourceGraphic")
  .attr("result", "upperLayer")
  .attr("operator", "dilate")
  .attr("radius", "2 2");

filter.append("feMorphology")
  .attr("in", "SourceAlpha")
  .attr("result", "enlargedAlpha")
  .attr("operator", "dilate")
  .attr("radius", "3 3");

filter.append("feGaussianBlur")
  .attr("in", "enlargedAlpha")
  .attr("result", "bluredAlpha")
  .attr("stdDeviation", "5");
  
filter.append("feOffset")
  .attr("in", "bluredAlpha")
  .attr("result", "lowerLayer")
  .attr("dy", "2");

var feMerge = filter.append("feMerge");
feMerge.append("feMergeNode")
  .attr("in","lowerLayer");
feMerge.append("feMergeNode")
  .attr("in","upperLayer");

svg.append("rect")
    .attr("rx", 2)
    .attr("ry", 2)
	.attr("x", "20%")
  .attr("y", "20%")
  .attr("width", "60%")
  .attr("height", "60%")
  .attr("fill", "white")
  .style("filter", "url(#coolShadow)");
  
  
  
  
  
  
  
  
&#13;
#drawRegion {
    width: 100%;
    height: 100%;
    display: inline-block;
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
    position: relative;
}
&#13;
<div id="drawRegion">

</div>
<script src="https://d3js.org/d3.v5.min.js"></script>
&#13;
&#13;
&#13;