Как в SVG сделать вокруг рисунка гало-контур?
У меня есть рисунок SVG, пример кода ниже.
Необходимо сделать вокруг всего рисунка белый гало-контур шириной N пикселей через фильтр.
Необходимо найти решение не для конкретного этого рисунка, а именно фильтр, который я смогу к любому рисунку применить. Например к тексту, или набору фигур.
Контекст вопроса это создание стикеров для Telegram, где гало-контур является рекомендуемой составляющей.
div {
background-color: blue;
}
<div>
<svg id="placeholder" width="600" height="600" version="1.1" viewBox="-120 -120 240 240" preserveAspectRatio="none">
<path d="M25.9-96.6C38.3-92.4 41.3-99.8 54-93.5 65.7-85.7 60.9-79.3 70.7-70.7 79.3-60.9 85.7-65.7 93.5-54 99.8-41.3 92.4-38.3 96.6-25.9 99.1-13.1 107.1-14.1 108 0 107.1 14.1 99.1 13.1 96.6 25.9 92.4 38.3 99.8 41.3 93.5 54 85.7 65.7 79.3 60.9 70.7 70.7 60.9 79.3 65.7 85.7 54 93.5 41.3 99.8 38.3 92.4 25.9 96.6 13.1 99.1 14.1 107.1 0 108 -14.1 107.1-13.1 99.1-25.9 96.6 -38.3 92.4-41.3 99.8-54 93.5 -65.7 85.7-60.9 79.3-70.7 70.7 -79.3 60.9-85.7 65.7-93.5 54 -99.8 41.3-92.4 38.3-96.6 25.9 -99.1 13.1-107.1 14.1-108 0 -107.1-14.1-99.1-13.1-96.6-25.9 -92.4-38.3-99.8-41.3-93.5-54 -85.7-65.7-79.3-60.9-70.7-70.7 -60.9-79.3-65.7-85.7-54-93.5 -41.3-99.8-38.3-92.4-25.9-96.6 -13.1-99.1-14.1-107.1 0-108 14.1-107.1 13.1-99.1 25.9-96.6 38.3-92.4 41.3-99.8 54-93.5 65.7-85.7 60.9-79.3 70.7-70.7 79.3-60.9 85.7-65.7 93.5-54 99.8-41.3 92.4-38.3 96.6-25.9 99.1-13.1 107.1-14.1 108 0 107.1 14.1 99.1 13.1 96.6 25.9 92.4 38.3 99.8 41.3 93.5 54 85.7 65.7 79.3 60.9 70.7 70.7 60.9 79.3 65.7 85.7 54 93.5 41.3 99.8 38.3 92.4 25.9 96.6 13.1 99.1 14.1 107.1 0 108 -14.1 107.1-13.1 99.1-25.9 96.6 -38.3 92.4-41.3 99.8-54 93.5 -65.7 85.7-60.9 79.3-70.7 70.7 -79.3 60.9-85.7 65.7-93.5 54 -99.8 41.3-92.4 38.3-96.6 25.9 -99.1 13.1-107.1 14.1-108 0 -107.1-14.1-99.1-13.1-96.6-25.9 -92.4-38.3-99.8-41.3-93.5-54 -85.7-65.7-79.3-60.9-70.7-70.7 -60.9-79.3-65.7-85.7-54-93.5 -41.3-99.8-38.3-92.4-25.9-96.6 -13.1-99.1-14.1-107.1 0-108 14.1-107.1 13.1-99.1 25.9-96.6 38.3-92.4 41.3-99.8 54-93.5 65.7-85.7 60.9-79.3 70.7-70.7" style="fill:yellow;stroke:black; stroke-width:4"/>
</svg>
</div>
Ответы (3 шт):
Регулировка: radius в smallZoom - отступ от исходного изображения, radius в bigZoom - толщина гало
body {
background-color: blue;
}
#placeholder {
width: 300px;
height: 300px;
}
h1 {
font-size: 150px;
text-align: center;
filter: url(#galo);
margin: 0;
}
<h1>Lorem</h1>
<svg id="placeholder" preserveAspectRatio="none" version="1.1" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="galo">
<feMorphology operator="dilate" radius="5" result="smallZoom"/>
<feMorphology operator="dilate" radius="2" result="bigZoom"/>
<feFlood flood-color="white" result="whiteBg"/>
<feComposite in="bigZoom" in2="smallZoom" operator="out" result="galo"/>
<feComposite in="whiteBg" in2="galo" operator="in" result="whiteGalo"/>
<feMerge>
<feMergeNode in="whiteGalo"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<path d="m175.9 53.4c12.4 4.2 15.4-3.2 28.1 3.1 11.7 7.8 6.9 14.2 16.7 22.8 8.6 9.8 15 5 22.8 16.7 6.3 12.7-1.1 15.7 3.1 28.1 2.5 12.8 10.5 11.8 11.4 25.9-0.9 14.1-8.9 13.1-11.4 25.9-4.2 12.4 3.2 15.4-3.1 28.1-7.8 11.7-14.2 6.9-22.8 16.7-9.8 8.6-5 15-16.7 22.8-12.7 6.3-15.7-1.1-28.1 3.1-12.8 2.5-11.8 10.5-25.9 11.4-14.1-0.9-13.1-8.9-25.9-11.4-12.4-4.2-15.4 3.2-28.1-3.1-11.7-7.8-6.9-14.2-16.7-22.8-8.6-9.8-15-5-22.8-16.7-6.3-12.7 1.1-15.7-3.1-28.1-2.5-12.8-10.5-11.8-11.4-25.9 0.9-14.1 8.9-13.1 11.4-25.9 4.2-12.4-3.2-15.4 3.1-28.1 7.8-11.7 14.2-6.9 22.8-16.7 9.8-8.6 5-15 16.7-22.8 12.7-6.3 15.7 1.1 28.1-3.1 12.8-2.5 11.8-10.5 25.9-11.4 14.1 0.9 13.1 8.9 25.9 11.4 12.4 4.2 15.4-3.2 28.1 3.1 11.7 7.8 6.9 14.2 16.7 22.8 8.6 9.8 15 5 22.8 16.7 6.3 12.7-1.1 15.7 3.1 28.1 2.5 12.8 10.5 11.8 11.4 25.9-0.9 14.1-8.9 13.1-11.4 25.9-4.2 12.4 3.2 15.4-3.1 28.1-7.8 11.7-14.2 6.9-22.8 16.7-9.8 8.6-5 15-16.7 22.8-12.7 6.3-15.7-1.1-28.1 3.1-12.8 2.5-11.8 10.5-25.9 11.4-14.1-0.9-13.1-8.9-25.9-11.4-12.4-4.2-15.4 3.2-28.1-3.1-11.7-7.8-6.9-14.2-16.7-22.8-8.6-9.8-15-5-22.8-16.7-6.3-12.7 1.1-15.7-3.1-28.1-2.5-12.8-10.5-11.8-11.4-25.9 0.9-14.1 8.9-13.1 11.4-25.9 4.2-12.4-3.2-15.4 3.1-28.1 7.8-11.7 14.2-6.9 22.8-16.7 9.8-8.6 5-15 16.7-22.8 12.7-6.3 15.7 1.1 28.1-3.1 12.8-2.5 11.8-10.5 25.9-11.4 14.1 0.9 13.1 8.9 25.9 11.4 12.4 4.2 15.4-3.2 28.1 3.1 11.7 7.8 6.9 14.2 16.7 22.8" fill="green" stroke="#000" stroke-width="4" filter="url(#galo)" />
</svg>
Немного другой вариант комбинации SVG фильтров, но основа та же для формирования гало контура вокруг текста или изображения svg, png
<feMorphology operator="dilate" in="SourceAlpha"
radius="5" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="2" result="e2" />
Фильтр
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 0 1 0" result="outline2"/>
Обеспечивает цвет контура, в данном случае, когда R=G=B=1, цвет рамки получается белый
#1. Вариант применения фильтра к тексту и фигуре SVG
<style>
div {
background-color: blue;
}
</style>
<div>
<svg id="placeholder" width="600" height="600" version="1.1" viewBox="-120 -120 240 240" preserveAspectRatio="none" >
<defs>
<filter id="groupborder"
x="-20%" y="-20%" width="200%" height="200%">
<feMorphology operator="dilate" in="SourceAlpha"
radius="5" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="2" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 0 1 0" result="outline2"/>
<feComposite in="outline2" in2="SourceGraphic"
operator="over" result="output"/>
</filter>
</defs>
<path filter="url(#groupborder)" transform="scale(.7)" d="M25.9-96.6C38.3-92.4 41.3-99.8 54-93.5 65.7-85.7 60.9-79.3 70.7-70.7 79.3-60.9 85.7-65.7 93.5-54 99.8-41.3 92.4-38.3 96.6-25.9 99.1-13.1 107.1-14.1 108 0 107.1 14.1 99.1 13.1 96.6 25.9 92.4 38.3 99.8 41.3 93.5 54 85.7 65.7 79.3 60.9 70.7 70.7 60.9 79.3 65.7 85.7 54 93.5 41.3 99.8 38.3 92.4 25.9 96.6 13.1 99.1 14.1 107.1 0 108 -14.1 107.1-13.1 99.1-25.9 96.6 -38.3 92.4-41.3 99.8-54 93.5 -65.7 85.7-60.9 79.3-70.7 70.7 -79.3 60.9-85.7 65.7-93.5 54 -99.8 41.3-92.4 38.3-96.6 25.9 -99.1 13.1-107.1 14.1-108 0 -107.1-14.1-99.1-13.1-96.6-25.9 -92.4-38.3-99.8-41.3-93.5-54 -85.7-65.7-79.3-60.9-70.7-70.7 -60.9-79.3-65.7-85.7-54-93.5 -41.3-99.8-38.3-92.4-25.9-96.6 -13.1-99.1-14.1-107.1 0-108 14.1-107.1 13.1-99.1 25.9-96.6 38.3-92.4 41.3-99.8 54-93.5 65.7-85.7 60.9-79.3 70.7-70.7 79.3-60.9 85.7-65.7 93.5-54 99.8-41.3 92.4-38.3 96.6-25.9 99.1-13.1 107.1-14.1 108 0 107.1 14.1 99.1 13.1 96.6 25.9 92.4 38.3 99.8 41.3 93.5 54 85.7 65.7 79.3 60.9 70.7 70.7 60.9 79.3 65.7 85.7 54 93.5 41.3 99.8 38.3 92.4 25.9 96.6 13.1 99.1 14.1 107.1 0 108 -14.1 107.1-13.1 99.1-25.9 96.6 -38.3 92.4-41.3 99.8-54 93.5 -65.7 85.7-60.9 79.3-70.7 70.7 -79.3 60.9-85.7 65.7-93.5 54 -99.8 41.3-92.4 38.3-96.6 25.9 -99.1 13.1-107.1 14.1-108 0 -107.1-14.1-99.1-13.1-96.6-25.9 -92.4-38.3-99.8-41.3-93.5-54 -85.7-65.7-79.3-60.9-70.7-70.7 -60.9-79.3-65.7-85.7-54-93.5 -41.3-99.8-38.3-92.4-25.9-96.6 -13.1-99.1-14.1-107.1 0-108 14.1-107.1 13.1-99.1 25.9-96.6 38.3-92.4 41.3-99.8 54-93.5 65.7-85.7 60.9-79.3 70.7-70.7" style="fill:#E4B90B;stroke:black; stroke-width:4"/>
<text filter="url(#groupborder)" x="-32" y="12" font-size="2em" font-weight="700" fill="black">TeXt</text>
</svg>
</div>
#2. Вариант применения фильтра к изображению PNG
Очень удобно обвести фигуру гало рамкой, когда основной цвет изображения совпадает или близок к окружающему фону
<style>
.container {
width:50vw;
height:auto;
background-color: #111;
}
</style>
<div class="container">
<svg id="placeholder" viewBox="0 0 300 400" >
<defs>
<filter id="groupborder"
x="-20%" y="-20%" width="200%" height="200%">
<feMorphology operator="dilate" in="SourceAlpha"
radius="10" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="5" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 0 1 0" result="outline2"/>
<feComposite in="outline2" in2="SourceGraphic"
operator="over" result="output"/>
</filter>
</defs>
<image filter="url(#groupborder)" xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/300px-Tux.svg.png" />
</svg>
</div>
Другой цвет фона
<style>
.container {
width:50vw;
height:auto;
background-color: dodgerblue;
}
</style>
<div class="container">
<svg id="placeholder" viewBox="0 0 300 400" >
<defs>
<filter id="groupborder"
x="-20%" y="-20%" width="200%" height="200%">
<feMorphology operator="dilate" in="SourceAlpha"
radius="10" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="5" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 0 1 0" result="outline2"/>
<feComposite in="outline2" in2="SourceGraphic"
operator="over" result="output"/>
</filter>
</defs>
<image filter="url(#groupborder)" xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/300px-Tux.svg.png" />
</svg>
</div>
Возникла идея, а если объединить два растровых изображения в одну группу SVG и применить к ней фильтр, то рамка будет обводить каждое растровое изображение или их суммарное значение.
Второе изображение уменьшено в два раза, чтобы создать образ мамаши с пингвинёнком на коленях
<g filter="url(#groupborder)">
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/300px-Tux.svg.png" />
<image transform="scale(0.5) translate(300 200)" xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/300px-Tux.svg.png" />
</g>
<style>
.container {
width:50vw;
height:auto;
background-color: dodgerblue;
}
</style>
<div class="container">
<svg id="placeholder" viewBox="0 0 400 400" >
<defs>
<filter id="groupborder"
x="-20%" y="-20%" width="200%" height="200%">
<feMorphology operator="dilate" in="SourceAlpha"
radius="10" result="e1" />
<feMorphology operator="dilate" in="SourceAlpha"
radius="5" result="e2" />
<feComposite in="e1" in2="e2" operator="xor"
result="outline"/>
<feColorMatrix type="matrix" in="outline"
values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
0 0 0 1 0" result="outline2"/>
<feComposite in="outline2" in2="SourceGraphic"
operator="over" result="output"/>
</filter>
</defs>
<g filter="url(#groupborder)">
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/300px-Tux.svg.png" />
<image transform="scale(0.5) translate(300 200)" xlink:href="https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/300px-Tux.svg.png" />
</g>
</svg>
</div>
