Измените непрозрачность тени частично в SVG, используя фильтры и d3.js - PullRequest
0 голосов
/ 03 июня 2018

Как я могу частично изменить непрозрачность тени в svg, используя фильтры и d3.js?

Вот как я хотел бы, чтобы моя тень выглядела так: 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 голосов
/ 04 июня 2018

Лучший способ добиться того, что вы хотите сделать, - это набрать обратно у-радиус во второй феморфологии и у-феофсет.Существуют способы на самом деле выборочно уменьшить непрозрачность, но они вызовут разрывы в вашей тени, чего вы, вероятно, не хотите.

(Также вам нужно было расширить область фильтра - что я и сделаю для вас здесь).

Интересно, почему вы используете feMorphology для расширения исходного прямоугольника?Если вам нужен больший прямоугольник со слегка закругленными углами, вы можете просто нарисовать его прямо в SVG - он будет более производительным.feMorphology - медленная операция.

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)");
  
  
  
  
  
  
  
  
#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>
0 голосов
/ 04 июня 2018

Вы можете одновременно играть с атрибутами opacity и dy.

Непрозрачность в глобальном масштабе сделает тень ярче или темнее (значение от 0 до 1).

The *Атрибут 1007 * (то же самое относится и к dx) перемещает тень по вертикали («перемещает источник света»).

Если dy равно 0, то тень центрируется на фигуре (светисточник чуть выше формы).Если (как в вашем случае) 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%");
...