mixable
mixable

Reputation: 1158

SVG: border outline for group of elements

I'd like to add a border to a number of elements which are grouped by <g>. As an example:

<g id="group">
  <circle cx="125" cy="125" r="65" fill="orange" />
  <line x1="50" y1="50" x2="200" y2="200" stroke="blue" stroke-width="4" />
</g>

Best case, the border should look like in the following picture. The distance between the elements and the border is not required (but nice to have). The main goal should be a single border (stroke) around the group elements.

group of elements

I found the picture in a tutorial, but there it was just to demonstrate what a group of elements may look like. So this doesn't help.

I already tried different solutions, but none of them worked as expected, e.g.

Any ideas, how to get a border around the group as shown in the picture?

Upvotes: 8

Views: 3794

Answers (2)

Eboubaker
Eboubaker

Reputation: 800

It won't work for complex shapes like yours, but you could simply add a rect around the group with the attribute stroke-dasharray like this (with pattern 3 dashes followed by 3 gaps)

<svg width="150" height="80" viewBox="0 0 150 80">
  <rect stroke-dasharray="3 3" x="8" y="8" width="130" height="65" fill="none" stroke="blue"></rect>
  <g>
    <rect x="10" y="10" width="50" height="60" fill="lime"></rect>
    <rect x="65" y="40" width="70" height="30" fill="lime"></rect>
  </g>
</svg>

Upvotes: -1

r3mainer
r3mainer

Reputation: 24557

It would be difficult to get the dashed stroke shown in the image you provided. But a solid outline should be possible. Here's an example:

<svg width="250" height="250" viewBox="0 0 250 250">
  <defs>
    <filter id="groupborder" filterUnits="userSpaceOnUse"
            x="0" y="0" width="250" height="250">
      <feMorphology operator="dilate" in="SourceAlpha"
                    radius="8" result="e1" />
      <feMorphology operator="dilate" in="SourceAlpha"
                    radius="10" result="e2" />
      <feComposite in="e1" in2="e2" operator="xor"
                   result="outline"/>
      <feColorMatrix type="matrix" in="outline"
                     values="1 0 0 0 0
                             0 1 0 0 0
                             0 0 1 0 0
                             0 0 0 .3 0" result="outline2"/>
      <feComposite in="outline2" in2="SourceGraphic"
                   operator="over" result="output"/>
    </filter>
  </defs>
  <g id="group" filter="url(#groupborder)">
    <circle cx="125" cy="125" r="65" fill="orange" />
    <line x1="50" y1="50" x2="200" y2="200" stroke="blue" stroke-width="4" />
  </g>
</svg>

Here's how it works:

<feMorphology operator="dilate" in="SourceAlpha" radius="8" result="e1" />

Uses a dilate operation to fatten up the graphic elements. By using the source alpha as the input image, this results in black regions corresponding to the graphic elements in the image, and white everywhere else.

<feMorphology operator="dilate" in="SourceAlpha" radius="10" result="e2" />

The same filter again, but with a larger amount of dilation, resulting in a slightly fatter image

<feComposite in="e1" in2="e2" operator="xor" result="outline"/>

These dilated results are combined using an XOR operation that leaves behind a black outline.

<feColorMatrix type="matrix" in="outline"
values="1 0 0 0 0
        0 1 0 0 0
        0 0 1 0 0
        0 0 0 .3 0" result="outline2"/>

This filter multiplies the alpha component of the outline by 0.3 so it appears grey instead of solid black.

<feComposite in="outline2" in2="SourceGraphic" operator="over" result="output"/>

Finally, add this outline to the original image.

Upvotes: 11

Related Questions