Как объединить две фигуры в svg?

например, у меня есть две формы: круг и прямоугольник. Я хочу превратить их в одну фигуру. Есть ли способы сделать это в svg-коде?

    <svg width="400" height="400">
     <defs>
    <g id="shape" fill="none" stroke="red">
      <rect x="40" y="50" width="40" height="70" />
      <circle cx="50" cy="50" r="50" />
    </g>
  </defs>

  <use xlink:href="#shape" x="50" y="50"  />
  <use xlink:href="#shape" x="200" y="50" />

</svg>

такой: like this

3 ответов


можно сделать <mask> или <clipPath> из двух фигур, а затем используйте это, чтобы замаскировать третью фигуру. Затем вы можете применить свою тень к этому.

<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>

Примечание: Если вам интересно, почему мы применяем тени родительской <g> здесь, это потому, что если мы применили его непосредственно к <rect> тень будет подчиняться клип тоже.


что не так с просто dropshadow на группе вокруг фигур?

    <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>

для тех, кто ищет ответ на фактический вопрос о том, как объединить две очерченные фигуры в одну очерченную форму (а не ставить тень на объединенную форму), вот возможное решение:

<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>

это по существу рисует круг с вырезанной из него формой прямоугольника и рисует прямоугольник с вырезанным из него кругом. Когда вы размещаете эти "пробитые" фигуры одна поверх другой, вы получаете то, что кажется один очерченный силуэт.

вот что на самом деле делает SVG:

  1. он определяет белый прямоугольник под названием "холст", который имеет тот же размер, ЧТО и SVG.
  2. он определяет две фигуры, которые должны быть объединены ("shape1 "и"shape2").
  3. он определяет маску для каждой фигуры, которая объединяет холст (который имеет заливку белого цвета) с формой (которая по умолчанию имеет заливку черного цвета). Обратите внимание, что при применении маски к фигуре часть отображается форма, соответствующая белой области маски, а часть, соответствующая черной части, скрыта.
  4. он рисует каждую форму с маской другой примененной формы.