SVG Drop Shadow Layering

I would like to shade behind the plot that I am doing with d3 and SVG, but I am having problems with overlapping shadows overlapping adjacent elements. Check out the image below to see how it looks at the moment. Note that the hexagons in the middle appear to be different heights because the shadows appear over some of them. What I would like to do is adjust the shadows so that they only appear in the background and not on top of other adjacent hexes.

Here's the code for how shadows are currently defined:

      var filter = defs.append("filter")
        .attr("id", "drop-shadow")
        .attr("height", "130%");

    // SourceAlpha refers to opacity of graphic that this filter will be applied to
    // convolve that with a Gaussian with standard deviation 3 and store result
    // in blur
    filter.append("feGaussianBlur")
        .attr("in", "SourceAlpha")
        .attr("stdDeviation", 1)
        .attr("result", "blur");

    // translate output of Gaussian blur to the right and downwards with 2px
    // store result in offsetBlur
    filter.append("feOffset")
        .attr("in", "blur")
        .attr("dx", 1)
        .attr("dy", 1)
        .attr("result", "offsetBlur");

    // overlay original SourceGraphic over translated blurred opacity by using
    // feMerge filter. Order of specifying inputs is important!
    var feMerge = filter.append("feMerge");

    feMerge.append("feMergeNode")
        .attr("in", "offsetBlur")
    feMerge.append("feMergeNode")
        .attr("in", "SourceGraphic");

      

Then these styles are applied to the hexagons:

d3.select(this).style("filter", "url(#drop-shadow)")

Shadows overlapping hexagaons

+3


source to share


2 answers


You don't need to create a whole bunch of duplicates in two layers. All you have to do is wrap all your hexagons in a group ( <g>

) and apply a filter to it.



<svg>
  <defs>
    <filter id="drop-shadow" width="150%" height="150%">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur"/>
      <feOffset in="blur" dx="2" dy="2" result="offsetBlur"/>
      <feMerge>
        <feMergeNode in="offsetBlur"/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>

  <rect x="75" y="75" width="50" height="50" fill="cyan"
        filter="url(#drop-shadow)"/>
  <rect x="75" y="25" width="50" height="50" fill="gold"
        filter="url(#drop-shadow)"/>
  <rect x="25" y="75" width="50" height="50" fill="lime"
        filter="url(#drop-shadow)"/>
  <rect x="25" y="25" width="50" height="50" fill="red"
        filter="url(#drop-shadow)"/>

  <g filter="url(#drop-shadow)" transform="translate(150,0)">
    <rect x="75" y="75" width="50" height="50" fill="cyan"/>
    <rect x="75" y="25" width="50" height="50" fill="gold"/>
    <rect x="25" y="75" width="50" height="50" fill="lime"/>
    <rect x="25" y="25" width="50" height="50" fill="red"/>
  </g>
</svg>
      

Run codeHide result


+4


source


enter image description hereI have a workaround. Essentially, it involves creating two sets of hexagons on different layers:

  • One set on the bottom layer without fills / strokes, but with shadows
  • One set on the top layer with all notes / strokes but no shadows


Since # 2 is above # 1, the shadows will not appear over any of the visible hexagons ...

-2


source







All Articles