Как заставить элемент <svg> расширяться или сжиматься до родительского контейнера?

112

Цель состоит в том, чтобы <svg>элемент расширился до размера его родительского контейнера, в данном случае a <div>, независимо от того, насколько большим или маленьким может быть этот контейнер.

Код:

<style>
    svg, #container{
        height: 100%;
        width: 100%;
    }
</style>

<div id="container">
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" >
         <rect x="0" y="0" width="100" height="100" />
    </svg>
</div>

Наиболее распространенное решение этой проблемы - установка viewBoxатрибута для <svg>элемента.

viewBox="0 0 widthOfContainer heightOfContainer"

Однако это не работает в тех случаях, когда элементы внутри <svg>элемента имеют заранее заданную ширину и / или высоту. Например, для <rect>элемента в приведенном выше коде явно заданы ширина и высота.

Таким образом, очевидным решением является использование% ширины и% высоты для этих элементов. Но нужно ли это вообще делать? Тем более, что <img src=test.svg >отлично работает и без проблем расширяется / сжимается с явно заданной <rect>высотой и шириной.

Если такие элементы, как <rect>и другие подобные элементы, должны иметь свою ширину и высоту, определенные в процентах, есть ли в Inkscape способ установить это так, чтобы все элементы в <svg>документе использовали процентную ширину, высоту и т. Д. Вместо фиксированных размеров ?

user782860
источник
1
Сохраните svg как файл, а затем ссылайтесь на него как на изображение, например <img src = "file.svg" />, и таким образом вы можете использовать ширину: 100% или высоту: 100%
Burimi

Ответы:

56

Дело viewBoxне в высоте контейнера, а в размере вашего рисунка. Определите viewBoxширину 100 единиц, затем определите rect10 единиц. После этого, каким бы большим вы ни масштабировали SVG, rectширина изображения будет составлять 10%.

Роберт
источник
33
Но вот вопрос: как масштабировать SVG?
Адриан Хайне
6
@AdrianLang Масштабирование происходит автоматически, когда вы устанавливаете размер объекта SVG, как это уже сделано в коде вопроса. Вот фиксированная версия примера .
robertc
Вы правы, отлично, это действительно работает для меня. Я думаю, моя проблема заключалась в свойствах высоты и ширины в моем корневом элементе svg.
Адриан Хайне
2
Я внес несколько незначительных изменений в эту скрипку, чтобы изменение размера было принудительным по горизонтали и вертикали без сохранения соотношения сторон, и заставил его работать в IE, в то время как представленная скрипта @robertc - нет. Надеюсь, это поможет кому-то в будущем!
Мистер Кримсон
3
По умолчанию ваш svg будет масштабироваться как можно больше, чтобы он был полностью видим, но сохранял его соотношение сторон (поэтому квадратный viewBox не полностью заполняет прямоугольный родительский элемент). Если вы действительно хотите заставить его полностью покрыть родительский контейнер, добавьте preserveAspectRatio = "none" к элементу SVG.
patricksurry
24

Предположим, у меня есть SVG, который выглядит так: pic1

И я хочу поместить его в div и заставить его быстро заполнять div. Мой способ сделать это так:

Сначала я открываю файл SVG в таком приложении, как inkscape. В File-> Document Properties я установил ширину документа 800 пикселей и высоту 600 пикселей (вы можете выбрать другие размеры). Затем я поместил SVG в этот документ.

pic2

Затем я сохраняю этот файл как новый файл SVG и получаю данные пути из этого файла. Теперь в HTML код, который творит чудеса, выглядит следующим образом:

<div id="containerId">    
    <svg
    id="svgId" 
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    x="0"
    y="0"
    width="100%"
    height="100%"
    viewBox="0 0 800 600"
    preserveAspectRatio="none">
       <path d="m0 0v600h800v-600h-75.07031l-431 597.9707-292.445315-223.99609 269.548825-373.97461h-271.0332z" fill="#f00"/>
    </svg>
</div>

Обратите внимание, что ширина и высота SVG установлены на 100%, поскольку мы хотим, чтобы он заполнял контейнер по вертикали и горизонтали, но ширина и высота viewBox такие же, как ширина и высота документа в inkscape, что составляет 800 пикселей X 600 пикселей. Следующее, что вам нужно сделать, это установить для preserveAspectRatio значение «none». Если вам нужна дополнительная информация об этом атрибуте, вот хорошая ссылка . Вот и все.

Еще одна вещь заключается в том, что этот код работает почти во всех основных браузерах, даже в старых, но в некоторых версиях Android и iOS вам нужно использовать код javascrip / jQuery, чтобы он был согласован. Я использую следующие функции в готовых документах и ​​функциях изменения размера:

$('#svgId').css({
    'width': $('#containerId').width() + 'px',
    'height': $('#containerId').height() + 'px'
});

Надеюсь, поможет!

Реза Барадаран Газорисанги
источник
5
+1 за примечание preserveAspectRatio. После охоты по максимуму и минимуму, чтобы SVG действительно растягивался (а не масштабировался) до div, это был правильный ответ.
adelphus
@Gazoris, Спасибо за этот замечательный ответ. есть вопрос по тому же самому. Что делать, если мой svg вложен. например, <svg> <svg id = "1"> </svg> <svg id = "2"> </svg> </svg> я хочу отображать svg 1 и 2 условно, и он должен принимать ширину и высоту контейнера. <div id = "container" style = "width: 200px; height: 200px;"> </div> не могли бы вы помочь мне в этом.
Прасад Параб
@ Реза Барадаран: Гений.
DanMad 03
6

Что работает для меня в последнее время , чтобы удалить все height=""и width=""атрибуты из <svg>тега и всех дочерних тегов. Затем вы можете использовать масштабирование, используя процент от высоты или ширины родительского контейнера.

Джефф Колбат
источник
5
Можете привести рабочий пример? Я ничего не могу заставить это сделать.
Michael
2

@robertc прав, но вы также должны заметить, что svg, #containersvg масштабируется экспоненциально для чего угодно, кроме 100% (один раз для #containerи один раз дляsvg ).

Другими словами, если я применил 50% h / w к обоим элементам, это фактически будет 50% от 50%, или 0,5 * 0,5, что равно 0,25 или 25% шкалы.

Один селектор отлично работает при использовании, как предлагает @robertc.

svg {
  width:50%;
  height:50%;
}
Джастин Патни
источник
Это потому , что ваш селектор svg, #containerсоответствует как на svgэлемент DOM и на #containerэлемент DOM. Я считаю, что вы вместо этого искали svg #container, но указание родителя не требуется, если вы все равно используете идентификатор.
Nit
Разве это не то, что я сказал: «один раз для #container и один раз для svg»?
Джастин Патни
1
Простите, вы правы, но ваш ответ немного странно сформулирован, что привело к недоразумению. Сначала это звучит так, как будто вы говорите о потенциальной проблеме.
Nit
1

Для вашего iphone вы можете использовать в голове баланс:

"width=device-width"
Винсент
источник