Обрезать в соответствии с рисунком SVG
У меня есть шаблоны, каждый из которых имеет одно изображение. Мне нужно, чтобы изображения масштабировались до полной ширины или высоты их контейнеров, которые являются путями, сохраняя при этом их пропорции. По сути, они должны вести себя как HTML-изображения, если вы установите min-width:100%; min-height:100%;
Я не использовал svgs раньше и не знаю, какие атрибуты нужно изменить, чтобы получить такой тип поведения. Я пробовал всевозможные комбинации viewBox
, preserveAspectRatio
, patternUnits
и больше, но я не могу получить то, что хочу.
1 ответ
Чтобы это сработало, нужно понять, как objectBoundingBox
единицы работают в SVG, а также как preserveAspectRatio
работает.
Единицы ограничивающего прямоугольника объекта
Размер и содержание градиентов, шаблонов и ряда других возможностей SVG могут быть определены в терминах размера объекта (path
, rect
, circle
) который рисуется путем указания objectBoundingBox
как блок. Противоположность всегда userSpaceOnUse
, который использует систему координат, в которой нарисована фигура.
Единицы ограничительной рамки объекта обычно используются по умолчанию для объявления размера и положения графического элемента заливки; вы измените это, установив patternUnits
собственность на <pattern>
элемент. Однако единицы пространства пользователя обычно являются значениями по умолчанию для любых единиц, используемых в графике контента; чтобы изменить это, вы установите patternContentUnits
имущество.
Итак, первый шаг: чтобы создать шаблон, который полностью заполняет форму, вам необходимо:
- Объявите высоту и ширину шаблона как 100% (или 1); по умолчанию они будут интерпретироваться относительно ограничительной рамки).
- декларировать
patternContentUnits="objectBoundingBox"
, - Увеличьте размер содержимого (вашего изображения), чтобы оно имело высоту и ширину 1.
Вы не можете использовать 100% в качестве синонима для 1 единицы ограничивающего прямоугольника объекта в самом содержимом шаблона (то есть в размерах изображения); проценты интерпретируются относительно размера SVG, а не objectBoundingBox.*
Я должен упомянуть, так как вы говорите, что ваши фигуры <path>
элементы, что ограничивающий прямоугольник объекта является наименьшим прямоугольником, который перпендикулярен системе координат, в которой рисуется путь, и содержит все точки пути. Это не включает инсульт. Например, прямая горизонтальная линия имеет ограничивающий прямоугольник нулевой высоты; угловая линия имеет ограничивающий прямоугольник, такой, что линия является диагональю прямоугольника. Если ваши пути имеют неудобную форму и / или не очень хорошо выровнены с системой координат, ограничивающий прямоугольник может быть намного больше, чем путь.
Сохранение пропорций
preserveAspectRatio
свойство применяется к изображениям и к любому элементу, который может иметь viewBox
свойство: родитель <svg>
вложенный <svg>
, <symbol>
, <marker>
а также <pattern>
, Для изображений соотношение сторон рассчитывается из соотношения ширины и высоты изображения, для всех остальных оно рассчитывается из чисел width:height в атрибуте viewBox.
Для любого типа элемента, если вы объявляете высоту или ширину для элемента, который не соответствует соотношению сторон, preserveAspectRatio
свойство определяет, будет ли содержимое растягиваться, чтобы соответствовать (none
), подгонянный под одно измерение и обрезанный в другом (slice
) или сжаты, чтобы вместить оба размера с дополнительным пространством (meet
); за meet
а также slice
В опциях вы также указываете, как выровнять содержимое в пространстве.
Однако важно отметить, что соотношение сторон доступного пространства рассчитывается в текущей системе координат, а не в пикселях экрана. Так что если viewBox или преобразование более высокого уровня изменило соотношение сторон, все равно можно искажать даже с помощью свойства preserveAspectRatio, установленного для текущего элемента.
Другая вещь, которую нужно знать, это то, что значение по умолчанию обычно не none
, Для обоих <image>
а также <pattern>
элементы, по умолчанию xMidYMid meet
то есть сжать, чтобы соответствовать и центрироваться. Конечно, это значение по умолчанию влияет только на элементы шаблона, если элемент шаблона имеет viewBox
свойство (в противном случае предполагается, что оно не имеет соотношения сторон для сохранения).
Какое значение вы хотите использовать для preserveAspectRatio
будет зависеть от имиджа и дизайна:
- Должно ли изображение быть растянуто, чтобы соответствовать форме
preserveAspectRatio="none"
? - Следует ли сохранять пропорции изображения, но рассчитывать их по размеру, чтобы они полностью соответствовали или покрывали форму?
В первом случае (растяжение) вам не нужно ничего делать с <pattern>
элемент (отсутствие viewBox означает отсутствие управления соотношением сторон), но вам нужно специально отключить управление соотношением сторон на изображении.
Напротив, если вы хотите избежать искажения изображения, вам необходимо:
- Задавать
viewBox
а такжеpreserveAspectRatio
свойства на<pattern>
элемент; - Установить
preserveAspectRatio
собственность на<image>
если вы хотите что-то другое, чем по умолчанию.
Рабочий пример
Эта скрипка показывает три способа получения изображения шаблона для заполнения формы.
В верхнем ряду отключено управление аспектами.
<!-- pattern1 - no aspect ratio control --> <pattern id="pattern1" height="100%" width="100%" patternContentUnits="objectBoundingBox"> <image height="1" width="1" preserveAspectRatio="none" xlink:href="/*url*/" /> </pattern>
Средний ряд имеет контроль соотношения сторон на
<image>
элемент, поэтому изображение обрезается, чтобы соответствовать шаблону, но изображение все еще искажается, когда шаблон рисуется в прямоугольнике, потому чтоobjectBoundingBox
Единицы, определяющие систему координат, различаются по высоте и ширине. (Изображение в круге не искажается, потому что ограничивающий прямоугольник круга является квадратом.)<!-- pattern2 - aspect ratio control on the image only --> <pattern id="pattern2" height="100%" width="100%" patternContentUnits="objectBoundingBox"> <image height="1" width="1" preserveAspectRatio="xMidYMid slice" xlink:href="/*url*/" /> </pattern>
Нижний ряд имеет
preserveAspectRatio
установить как на изображение и шаблон (а такжеviewBox
установить по шаблону). Изображение обрезается, но не растягивается.<!-- pattern3 - aspect ratio control on both image and pattern --> <pattern id="pattern3" height="100%" width="100%" patternContentUnits="objectBoundingBox" viewBox="0 0 1 1" preserveAspectRatio="xMidYMid slice"> <image height="1" width="1" preserveAspectRatio="xMidYMid slice" xlink:href="/*url*/" /> </pattern>
Исходное изображение Стефана Краузе из Wikimedia Commons. Исходное соотношение сторон составляет 4:6 портретного режима.
* Исправление 2015-04-03