How can I merge two shapes in svg?

What's wrong with just a dropshadow on a group around the shapes?

    <svg width="400" height="400">
  <defs>   
    <filter id="shadow">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
      <feOffset dx="3" dy="3"/>
      <feMerge>
        <feMergeNode/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>

  <g filter="url(#shadow)">
      <rect x="40" y="50" width="40" height="70" fill="red"/>
      <circle cx="50" cy="50" r="50" fill="red"/>
  </g>

</svg>

You can make a <mask> or a <clipPath> from the two shapes and then use that to mask a third shape. You can then apply your drop shadow to that.

<svg width="400" height="400">
  <defs>
    <clipPath id="shape">
      <rect x="40" y="50" width="40" height="70" />
      <circle cx="50" cy="50" r="50" />
    </clipPath>
    
    <filter id="shadow">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
      <feOffset dx="3" dy="3"/>
      <feMerge>
        <feMergeNode/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>

  <g filter="url(#shadow)">
    <rect width="100%" height="100%" fill="red"
          clip-path="url(#shape)"/>
  </g>

</svg>

Note: if you are wondering why we are applying the drop shadow to a parent <g> here, it is because if we applied it directly to the <rect>, the drop shadow would be subject to the clip also.


For anyone looking for the answer to the actual question of how to combine two outlined shapes into a single outlined shape (rather than putting a drop shadow on the combined shape), here is a possible solution:

<svg width="400" height="400">
    <defs>
        <rect id="canvas" width="100%" height="100%" fill="white" />
        <rect id="shape1" x="40" y="50" width="40" height="70" />
        <circle id="shape2" cx="50" cy="50" r="50" />
        <mask id="shape1-cutout">
            <use href="#canvas"  />
            <use href="#shape1"  />
        </mask>
        <mask id="shape2-cutout">
            <use href="#canvas"  />
            <use href="#shape2"  />
        </mask>
    </defs>
    <use href="#shape1" stroke="red" fill="none" mask="url(#shape2-cutout)" />
    <use href="#shape2" stroke="red" fill="none" mask="url(#shape1-cutout)" />
</svg>

This essentially draws the circle with the rectangle shape cut out of it and draws the rectangle with the circle cut out of it. When you place these "punched out" shapes one on top of the other, you get what appears to be a single outlined shape.

Here's what the SVG actually does:

  1. It defines a white rectangle called "canvas" that is the same size as the SVG.
  2. It defines the two shapes that are to be combined ("shape1" and "shape2").
  3. It defines a mask for each shape that combines the canvas (which has a fill of white) with the shape (which has a fill of black by default). Note that when you apply a mask to a shape, the part of the shape that corresponds to the white area of the mask is shown, while the part that corresponds with black part is hidden.
  4. It draws each shape with the the mask of the other shape applied.

Tags:

Html

Svg