SVG уменьшенный путь с шаблоном заполнения - PullRequest
0 голосов
/ 02 октября 2019

Я пытаюсь нарисовать фигуру с путем, который должен быть уменьшен, как в этом решении Найти параллельный или смещенный путь SVG Я использую фильтр "эрозия", но с шаблоном он не работает: шаблондеформирован.

Есть ли способ сделать это без решения bezier.js, с чистым SVG / CSS?

Вот пример моей проблемы, я хочу иметь формусправа с рисунком слева.

<!DOCTYPE html>
<html>
    <body>
        <svg>
            <defs>
                <pattern id="circ" x="0" y="0" width="30" height="30" patternUnits="userSpaceOnUse">
                    <rect fill="blue" width="100%" height="100%" />
                    <circle cx="10" cy="10" r="10" fill="green" />
                </pattern>
                <filter id="erode">
                    <feMorphology in="SourceGraphic" operator="erode" radius="10"/>
                </filter>
                <path id="thing" d="M 0,0 H 50 A 35,35 0 1 0 100,50 V 75 C 50,125 0,85 0,85 Z" />
            </defs>
            <use href="#thing" fill="url(#circ)" width="400" height="400" filter="#erode"/>
            <use x="100" href="#thing" filter="url(#erode)" fill="url(#circ)" width="400" height="400" />
        </svg>
    </body>
</html>

Ответы [ 2 ]

2 голосов
/ 02 октября 2019

Вы можете расширить фильтр, чтобы сделать эту работу. Кажется, есть ошибка, разрушающая фигуры, заполненные шаблоном, - это неправильный выбор минимума альфа-каналов в радиусе. Но если вы начнете с SourceAlpha, а не с SourceGraphic, а затем создадите свою маску, используя переносы компонентов, это, похоже, будет работать.

           <svg>
            <defs>
                <pattern id="circ" x="0" y="0" width="30" height="30" patternUnits="userSpaceOnUse">
                    <rect fill="blue" width="100%" height="100%" />
                    <circle cx="10" cy="10" r="10" fill="green" />
                </pattern>
              <filter id="erode3">
<feMorphology in="SourceAlpha" result="eroded"
operator="erode" radius="10"/>
             <feComponentTransfer>
               <feFuncR type="discrete" tableValues="1 0"/>
               <feFuncG type="discrete" tableValues="1 0"/>
               <feFuncB type="discrete" tableValues="1 0"/>
              </feComponentTransfer>
            <feComposite operator ="in" in="SourceGraphic"/>
</filter>

                <path id="thing" d="M 0,0 H 50 A 35,35 0 1 0 100,50 V 75 C 50,125 0,85 0,85 Z" />
            </defs>
            <use href="#thing" fill="url(#circ)" width="400" height="400" filter="url(#erode3)"/>
            <use x="100" href="#thing" filter="url(#erode)" fill="url(#circ)" width="400" height="400" />
        </svg>
2 голосов
/ 02 октября 2019

Да. Вы можете использовать маску.

svg {
  width: 300px;
}

.purple {
  fill: rebeccapurple;
}

.reduce-me {
  mask: url(#reducer);
}

#reduce-amount {
  stroke-width: 5px;
}
<svg viewBox="0 0 100 100">
  <path class="purple"
        d="M 50,10 Q 100,10, 50,50 Q 0,90, 50,90 
           Q 100,90, 50,50 Q 0,10, 50,10 Z"/>
</svg>


<svg viewBox="0 0 100 100">
  <defs>
    <!-- the shared path that is used by both the purple path and the mask -->
    <path id="shared-path"
          id="p" d="M 50,10 Q 100,10, 50,50 Q 0,90, 50,90
                    Q 100,90, 50,50 Q 0,10, 50,10 Z" />

    <!-- a mask that shrinks the shape by half the stroke-width -->
    <mask id="reducer">
      <use id="reduce-amount" xlink:href="#shared-path"
           fill="white" stroke="black"/>
    </mask>
  </defs>

  <!-- the shape that gets reduced -->
  <use class="purple reduce-me" xlink:href="#shared-path"/>
</svg>

Как это работает

Если мы просто визуализируем, как выглядит маска (справа), мы можем видетькак это работает.

svg {
  width: 300px;
}

.purple {
  fill: rebeccapurple;
}

.reduce-me {
  mask: url(#reducer);
}

#reduce-amount {
  stroke-width: 10px;
}
<svg viewBox="0 0 100 100">
  <path class="purple"
        d="M 50,10 Q 100,10, 50,50 Q 0,90, 50,90 
           Q 100,90, 50,50 Q 0,10, 50,10 Z"/>
</svg>


<svg viewBox="0 0 100 100">
  <defs>
    <!-- the shared path that is used by both the purple path and the mask -->
    <path id="shared-path"
          id="p" d="M 50,10 Q 100,10, 50,50 Q 0,90, 50,90
                    Q 100,90, 50,50 Q 0,10, 50,10 Z" />
  </defs>

  <use id="reduce-amount" xlink:href="#shared-path"
       fill="white" stroke="black"/>
</svg>

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

Вы можете изменить величину уменьшения формы, изменив значение stroke-width в классе .reduce-amount.

НедостаткиЭтот метод: 1. вам нужна маска для каждой формы контура 2. вы не можете установить стиль обводки для формы уменьшенного размера. Однако вы можете смоделировать цвет обводки, наложив два контура с разными величинами сокращения.

...