Я хотел бы добавить границу для элементов, которые сгруппированы. В качестве примера:
<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>
При наилучшем варианте, граница должна выглядеть как рисунке.
Расстояние между элементами и границей не требуется (но лучше её иметь).
Основной целью должна быть единая граница вокруг элементов группы.
Я нашел изображение в учебнике, но там просто продемонстрировано, как может выглядеть группа элементов. Так что это не помогает.
Я уже пробовал разные решения, но ни одно из них не работает, как ожидалось, например:
feColorMatrix
и feMorphology
(см.
Этот пост). Но в этом случае цвет элементов изменяется при применении
фильтра.stroke
и stroke-width
приводит к прямоугольной рамке
вокруг группы, что тоже не то, что я хочу. Какие есть идеи, как получить границу вокруг группы, как показано на картинке?
Трудно получить dashed stroke
, показанный на изображении, которое вы предоставили. Но сплошной контур сделать возможно. Вот пример:
<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>
Ниже, как это работает:
<feMorphology operator="dilate" in="SourceAlpha" radius="8" result="e1" />
Фильтр feMorphology
использует dilate (расширенную) операцию для для утолщения графических элементов.
Используется исходный альфа канал в качестве входного изображения, это приводит к появлению черных областей, соответствующих графическим элементам изображения, и белого цвета в остальных частях.
<feMorphology operator="dilate" in="SourceAlpha" radius="10" result="e2" />
Используя тот же фильтр снова, но с большим количеством dilation
, что приводит к слегка более плотному изображению, и это приводит к появлению черных областей, соответствующих графическим элементам изображения, и белого цвета в остальных частях.
<feComposite in="e1" in2="e2" operator="xor" result="outline"/>
Эти расширенные результаты объединяются с использованием операции XOR, которая оставляет черный контур.
<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"/>
Этот фильтр умножает альфа-компонент контура на 0,3, поэтому он выглядит серым, а не сплошным черным.
<feComposite in="outline2" in2="SourceGraphic" operator="over" result="output"/>
Наконец, добавьте этот вывод в исходное изображение.
Источник: SVG: border outline for group of elements @squeamish ossifrage Прим. переводчика
На мой взгляд эта тема интересна, открывает широкие горизонты для творчества и может иметь практическое применение.
применение группы фильтров дает возможность получить контур любой сложности без применения патчей и стандартных команд обводки
Изменяя параметры фильтра feColorMatrix
можно получить практически любой цвет контура
применение фильтра feMorphology
позволяет изменять ширину обводки и
зазор между основной фигурой и обводкой
Пример получения зелёного контура
Для этого выставляем параметры фильтра feColorMatrix
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 0
0 0 0 1 0
0 0 0 0 0
0 0 0 1 0" result="outline2"/>
<svg width="250" height="250" viewBox="0 0 250 250" >
<defs>
<filter id="groupborder" filterUnits="userSpaceOnUse"
x="-20%" y="-20%" width="300" height="300">
<feMorphology operator="dilate" in="SourceAlpha"
radius="12" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="4" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 0
0 0 0 1 0
0 0 0 0 0
0 0 0 1 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>
Пример получения красного контура с расширением обводки
Для этого расширяем радиус действия у фильтра
<feMorphology operator="dilate" in="SourceAlpha"
radius="18" result="e1" />
<svg width="250" height="250" viewBox="0 0 250 250" >
<defs>
<filter id="groupborder" filterUnits="userSpaceOnUse"
x="-20%" y="-20%" width="300" height="300">
<feMorphology operator="dilate" in="SourceAlpha"
radius="18" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="3" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 1 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 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>
Пример изменения контура при изменении набора внутренних фигур
Просто добавим в группу элементов вторую линию и посмотрим как автоматически изменится обводка, формируемая фильтрами
<svg width="250" height="250" viewBox="0 0 250 250" >
<defs>
<filter id="groupborder" filterUnits="userSpaceOnUse"
x="-20%" y="-20%" width="300" height="300">
<feMorphology operator="dilate" in="SourceAlpha"
radius="18" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="3" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 1 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 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" />
<line x1="50" y1="200" x2="200" y2="50" stroke="blue" stroke-width="4" />
</g>
</svg>
Команда на изменение длины линии:
<polyline points="125,125 125,125" stroke="crimson" stroke-width="4" >
<animate attributeName="points" values="125,125 125,125;125,125 200,50;125,125 200,50;125,125 125,125" dur="7s" begin="0s" fill="freeze" restart="whenNotActive" repeatCount="indefinite"/>
</polyline>
Изменяется только конфигурация линии, а контур автоматически отслеживает эти изменения
<svg width="250" height="250" viewBox="0 0 250 250" >
<defs>
<filter id="groupborder" filterUnits="userSpaceOnUse"
x="-20%" y="-20%" width="300" height="300">
<feMorphology operator="dilate" in="SourceAlpha"
radius="18" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="3" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 1 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 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" />
<polyline points="125,125 125,125" stroke="purple" stroke-width="4" >
<animate attributeName="points" values="125,125 125,125;125,125 200,200;125,125 200,200;125,125 125,125" dur="7s" begin="0s" fill="freeze" restart="whenNotActive" repeatCount="indefinite" />
</polyline>
<polyline points="125,125 125,125" stroke="violet" stroke-width="4" >
<animate attributeName="points" values="125,125 125,125;125,125 50,50;125,125 50,50;125,125 125,125" dur="7s" begin="0s" fill="freeze" restart="whenNotActive" repeatCount="indefinite" />
</polyline>
<polyline points="125,125 125,125" stroke="dodgerblue" stroke-width="4" >
<animate attributeName="points" values="125,125 125,125;125,125 50,200;125,125 50,200;125,125 125,125" dur="7s" begin="0s" fill="freeze" restart="whenNotActive" repeatCount="indefinite" />
</polyline>
<polyline points="125,125 125,125" stroke="crimson" stroke-width="4" >
<animate attributeName="points" values="125,125 125,125;125,125 200,50;125,125 200,50;125,125 125,125" dur="7s" begin="0s" fill="freeze" restart="whenNotActive" repeatCount="indefinite"/>
</polyline>
</g>
</svg>
Для этого добавляется команда анимации изменения ширины строки от 4px
до 90px
<circle cx="125" cy="125" r="65" fill="yellow" stroke="yellowgreen" stroke-width="4" stroke-dasharray="14 6.41" >
<animate attributeName="stroke-width" values="4;90;90;4;4;90" dur="7s" begin="click" fill="freeze" restart="whenNotActive">
</circle>
Начало анимации - клик по фигуре
<svg width="250" height="250" viewBox="0 0 250 250" >
<defs>
<filter id="groupborder" filterUnits="userSpaceOnUse"
x="-20%" y="-20%" width="300" height="300">
<feMorphology operator="dilate" in="SourceAlpha"
radius="10" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="3" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 0
0 0 0 0.5 0
0 0 0 0 0
0 0 0 1 0" result="outline2"/>
<feComposite in="outline2" in2="SourceGraphic"
operator="over" result="output"/>
</filter>
</defs>
<text x="110" y="100" font-size="18">click</text>
<g id="group" filter="url(#groupborder)" fill-opacity="0.8">
<circle cx="125" cy="125" r="65" fill="yellow" stroke="yellowgreen" stroke-width="4" stroke-dasharray="14 6.41" >
<animate attributeName="stroke-width" values="4;90;90;4;4;90" dur="7s" begin="click" fill="freeze" restart="whenNotActive" >
</circle>
</g>
</svg>
Добавляются две команды анимации: изменение длины линии и вращение линии:
<polyline points="125,125 125,125" stroke="purple" stroke-width="7" >
<animate id="poly" attributeName="points" values="125,125 125,125;125,125 50,50" dur="2s" begin="0s" fill="freeze" restart="whenNotActive" repeatCount="1" />
<animateTransform id="rotate1" attributeName="transform" type="rotate" values="0 125 125;720 125 125;0 125 125" begin="poly.end-1s" repeatCount="indefinite" dur="12s" />
</polyline>
<circle cx="125" cy="125" r="8" fill="#3196C9" stroke="purple" stroke-width="2" />
<svg width="250" height="250" viewBox="0 0 250 250" >
<defs>
<filter id="groupborder" filterUnits="userSpaceOnUse"
x="-20%" y="-20%" width="300" height="300">
<feMorphology operator="dilate" in="SourceAlpha"
radius="16" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="8" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 0
0 0 0 0.3 0
0 0 0 1 0
0 0 0 1 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="#AAD0A0" stroke="#4A8ECD" stroke-width="2" />
<polyline points="125,125 125,125" stroke="purple" stroke-width="7" >
<animate id="poly" attributeName="points" values="125,125 125,125;125,125 50,50" dur="2s" begin="0s" fill="freeze" restart="whenNotActive" repeatCount="1" />
<animateTransform id="rotate1" attributeName="transform" type="rotate" values="0 125 125;720 125 125;0 125 125" begin="poly.end-1s" repeatCount="indefinite" dur="12s" />
</polyline>
<circle cx="125" cy="125" r="8" fill="#3196C9" stroke="purple" stroke-width="2" />
</g>
</svg>
Анимация stroke-dasharray
<circle cx="125" cy="125" r="65" fill="yellow" stroke="yellowgreen" stroke-width="8" stroke-dasharray="20.41 0" >
<animate attributeName="stroke-dasharray" values="20.41 0;0 20.41;10 10.41;20.41 0" begin="click" dur="3.5s" repeatCount="indefinite"/>
</circle>
<svg width="250" height="250" viewBox="0 0 250 250" >
<defs>
<filter id="groupborder" filterUnits="userSpaceOnUse"
x="-20%" y="-20%" width="300" height="300">
<feMorphology operator="dilate" in="SourceAlpha"
radius="6" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="3" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 0
0 0 0 0.5 0
0 0 0 0 0
0 0 0 1 0" result="outline2"/>
<feComposite in="outline2" in2="SourceGraphic"
operator="over" result="output"/>
</filter>
</defs>
<text x="110" y="90" font-size="20">click</text>
<g id="group" filter="url(#groupborder)" fill-opacity="0.7">
<circle cx="125" cy="125" r="65" fill="yellow" stroke="yellowgreen" stroke-width="8" stroke-dasharray="20.41 0" >
<animate attributeName="stroke-dasharray" values="20.41 0;0 20.41;10 10.41;20.41 0" begin="click" dur="3.5s" repeatCount="indefinite"/>
</circle>
</g>
</svg>
Анимация stroke-width
, stroke-dasharray
<circle cx="125" cy="125" r="65" fill="yellow" stroke="yellowgreen" stroke-width="74" stroke-dasharray="1 19.41" >
<animate attributeName="stroke-dasharray" values="0 20.41;16 4.41;16 4.41; 0 20.41" begin="click" dur="3.5s" repeatCount="indefinite"/>
<svg width="250" height="250" viewBox="0 0 250 250" >
<defs>
<filter id="groupborder" filterUnits="userSpaceOnUse"
x="-20%" y="-20%" width="300" height="300">
<feMorphology operator="dilate" in="SourceAlpha"
radius="6" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="3" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 0
0 0 0 0.5 0
0 0 0 0 0
0 0 0 1 0" result="outline2"/>
<feComposite in="outline2" in2="SourceGraphic"
operator="over" result="output"/>
</filter>
</defs>
<text x="110" y="90" font-size="20">click</text>
<g id="group" filter="url(#groupborder)" fill-opacity="0.7">
<circle cx="125" cy="125" r="65" fill="yellow" stroke="yellowgreen" stroke-width="74" stroke-dasharray="1 19.41" >
<animate attributeName="stroke-dasharray" values="0 20.41;16 4.41;16 4.41; 0 20.41" begin="click" dur="3.5s" repeatCount="indefinite"/>
</circle>
</g>
</svg>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Как убрать расширениеhtml в адресной строке браузера
На маке и под виндой, нужно отображение контента шрифтом по умолчанию; то бишь в macOS San Francisco, в windows Segoe UI