Как манипулировать изображением внутри элемента SVG?
Проблема: не могу разобраться в правилах поведения изображения, являющегося заливкой svg-элемента с тегом <path>.
Я уже не знаю какие ключевые слова надо вбить в поисковик, чтобы найти соответствующую документацию, мучаюсь три месяца.
В тех статьях, что удается нагуглить описываются только примеры с <rect> и везде указано, что высота и ширина изображения задаются в теге <pattern>, но пытаясь их изменить в своем коде изображение только двигается по координатам, а иногда не двигается, или обрезается.
Каким-то чудом все-таки увеличивается иногда, но попытки воспроизвести то же самое с другим элементом заканчиваются провалом, так как изображения для фона не всегда удается подобрать одинакового разрешения.
Пытался убирать и viewbox и свойства ширины и высоты из тегов по очереди. Собственно сам код:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 330">
<defs>
<style>.a{fill:url(#test);stroke:#000;stroke-width:10px;}</style>
<pattern id="test" patternUnits="userSpaceOnUse" width="100%" height="100%"
viewbox="0 0 360 330">
<image xlink:href="https://i.pinimg.com/originals/4b/d7/fb/4bd7fb27221140b0c023e8fbec2b1285.jpg"
width="100%" height="100%" />
</pattern>
</defs>
<path class="a" d="M198.5,85.5c-65.45,5.64-120.09,40.55-136,90-15.1,46.95,9.53,92,27,124,16.24,29.73,37.8,69.19,81,84,37.9,13,71-.35,132-25,64.15-25.9,103-41.61,113-76,9.75-33.68-19.45-46.52-27-115-6.07-55,9.88-72.84-3-91C371.05,56.13,327.2,45.06,198.5,85.5Z"/>
</svg>
Никак не могу понять, какой из width и height за какое конкретно преобразование изображения отвечает.
Подскажите, пожалуйста, как друг от друга зависят viewbox в тегах <svg> и <pattern>, и как от них зависит каждый из значений width и height в тегах <pattern> и <image>?
И есть ли смысл манипулировать размером используемого для заливки изображения?
Может у меня имеются лишние свойства?
Какое свойство отвечает за увеличение этого изображения, не увеличивая размер самого svg-элемента, в конце концов?
Координаты (х,у) специально не задавал, так как они и без документации понятно чем управляют.
Ответы (1 шт):
У вас несколько объектов и факторов, которые отвечают за размеры и масштабирование элементов SVG.
Нужно разделить ваш код на несколько простых частей и разобраться, как получить необходимые размеры и отчего зависит масштабирование.
Выбранное изображение имеет размеры 1920 х 1080px
- В SVG размеры, показанного изображения, зависят от соотношения:
Еслиviewport / viewBox = 1,
то при равенстве размеров, изображение выводится в том же масштабе, как нарисовано.
viewportэтоwidthиheightв шапке SVG
<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080">
<image xlink:href="https://i.stack.imgur.com/h0qca.jpg"
width="100%" height="100%" />
</svg>
- При
viewport / viewBox < 1Изображение уменьшается
Например, для уменьшения изображения в два раза, уменьшаем width="960" и height="540" в два раза, при тех же значениях viewBox="0 0 1920 1080"
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="540" viewBox="0 0 1920 1080">
<image xlink:href="https://i.stack.imgur.com/h0qca.jpg"
width="100%" height="100%" />
</
То есть два пикселя, взятые во viewBox, уплотняются в один пиксель vireport за счёт этого происходит уменьшение размера
- При
viewport / viewBox > 1происходит увеличение размера.
В этом случае, как раз возможна обрезка изображения
<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 960 540">
<image xlink:href="https://i.stack.imgur.com/h0qca.jpg"/>
</svg>
viewBox="0 0 960 540" стал в два раза меньше, то есть захватил только половину изображения, остальное обрезалось, но в оставшейся части один пиксель viewBox растягивается до двух пикселей viewport, поэтому изображение увеличивается.
Другими словами viewport (это width, height SVG> это своеобразное окно, в котором мы видим результат вычислений масштабирования.
Для простоты усвоения, запомните простое правило: у viewBox всё наоборот:
- при увеличении viewBox изображение уменьшается
- при уменьшении viewBox изображение увеличивается
Более подробные объяснения с примерами можно посмотреть здесь
Практические советы
На первых шагах освоения SVG избегайте вложенных viewBox, так как при этом происходит многократное масштабирование и позиционирование, в которых легко запутаться.
Речь идет в этом конкретном примере о viewBox в pattern. Лучше указать фиксированные размеры.
Паттерн можно представить, как какую-то площадь, имеющие размеры, допустим 1920х1080px, которую нужно заполнить плитками допустим 100х100 px Заполнение идет порядно. Итого должно быть 19 плиток по горизонтали и 10 целых плиток по вертикали. Подробнее здесь
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1900 1080">
<defs>
<!--Одна плитка 100х100px в паттерне -->
<pattern id="test" patternUnits="userSpaceOnUse" width="100px" height="100px">
<rect width="100" height="100" fill="none" stroke="red" />
</pattern>
</defs>
<!-- Заполняемый плитками объект-->
<rect width="100%" height="100%" fill="none" stroke="black" stroke-width="4" style="fill:url(#test)" />
</svg>
Вместо нескольких плиток вы можете добавить в паттерн фотообои, то есть изображение. Необходимо, чтобы размеры паттерна и картинки совпадали.
.a {
fill:url(#test);
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1900 1080">
<defs>
<pattern id="test" patternUnits="userSpaceOnUse" width="1900px" height="1080px">
<image xlink:href="https://i.stack.imgur.com/h0qca.jpg" width="1900" height="1080" />
</pattern>
</defs>
<rect class="a" width="100%" height="100%" rx="3%" />
</svg>
Как видно, изображение получилось респонсивно.
Теперь вместо прямоугольника вы можете создать любой криволиниейный объект и заполнить его паттерном fill:url(#test);
.a{
fill:url(#test);
stroke:#000;
stroke-width:10px;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1900 1080">
<defs>
<pattern id="test" patternUnits="userSpaceOnUse" width="1900px" height="1080px">
<image xlink:href="https://i.stack.imgur.com/h0qca.jpg" width="1900" height="1080" />
</pattern>
</defs>
<path class="a" d="M198.5,85.5c-65.45,5.64-120.09,40.55-136,90-15.1,46.95,9.53,92,27,124,16.24,29.73,37.8,69.19,81,84,37.9,13,71-.35,132-25,64.15-25.9,103-41.61,113-76,9.75-33.68-19.45-46.52-27-115-6.07-55,9.88-72.84-3-91C371.05,56.13,327.2,45.06,198.5,85.5Z"/>
</svg>
Теперь размер вырезанного изображения зависит от размеров кривой (path class="a")