Как я могу сделать масштаб SVG с его родительским контейнером?

236

Я хочу иметь встроенную шкалу содержимого элемента SVG, когда размер не является родным. Конечно, я мог бы иметь его как отдельный файл и так масштабировать.

index.html: <img src="foo.svg" style="width: 100%;" />

foo.svg: <svg width="123" height="456"></svg>

Тем не менее, я хочу добавить дополнительные стили в SVG через CSS, так что связывать внешние стили нельзя. Как сделать встроенную шкалу SVG?

bjb568
источник
2
попробуйте precents в ширину и высоту SVG.
NCM
@ncm Как бы это сделать с JS?
Мауг говорит восстановить Монику

Ответы:

458

Чтобы указать координаты внутри SVG изображений независимо от масштабируемого размера изображения, используйте viewBoxатрибут элемент SVG , чтобы определить , что ограничивающая коробка изображения в системе координат изображения, а также использовать widthи heightатрибуты , чтобы определить , что ширина или высота по отношению к содержащей странице.

Например, если у вас есть следующее:

<svg>
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

Он будет отображаться как треугольник размером 10 на 20 пикселей:

10x20 треугольник

Теперь, если вы установите только ширину и высоту, это изменит размер элемента SVG, но не изменит масштаб треугольника:

<svg width=100 height=50>
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

10x20 треугольник

Если вы устанавливаете окно просмотра, это заставляет его преобразовывать изображение таким образом, чтобы данное поле (в системе координат изображения) масштабировалось так, чтобы оно соответствовало заданной ширине и высоте (в системе координат страницы). Например, чтобы увеличить треугольник до 100 на 50 пикселей:

<svg width=100 height=50 viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

100x50 треугольник

Если вы хотите увеличить его до ширины окна просмотра HTML:

<svg width="100%" viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

300x150 треугольник

Обратите внимание, что по умолчанию соотношение сторон сохраняется. Поэтому, если вы укажете, что элемент должен иметь ширину 100% и высоту 50 пикселей, он фактически будет масштабироваться только до высоты 50 пикселей (если у вас нет очень узкого окна):

<svg width="100%" height="50px" viewBox="0 0 20 10">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

100x50 треугольник

Если вы действительно хотите растянуть его горизонтально, отключите сохранение пропорций с помощью preserveAspectRatio=none:

<svg width="100%" height="50px" viewBox="0 0 20 10" preserveAspectRatio="none">
    <polygon fill=red stroke-width=0 
             points="0,10 20,10 10,0" />
</svg>

300x50 треугольник

(обратите внимание, что хотя в моих примерах я использую синтаксис, который работает для встраивания HTML, для включения примеров в качестве изображения в StackOverflow я вместо этого встраиваю в другой SVG, поэтому мне нужно использовать допустимый синтаксис XML)

Брайан Кэмпбелл
источник
1
Как вы делаете не только viewBox preserveAspectRatio, но и основной блок? Я хочу ширину: 100%; высота: авто для него.
bjb568
1
@ Чувак: я думаю, что пример с указанием width="100%"высоты и без указания высоты делает то, что вы хотите. Я добавил изображения для демонстрации. Он имеет ширину 100% и пропорционально увеличивает высоту. Если это не то, что вы ищете, вы можете уточнить, что вы имели в виду?
Брайан Кэмпбелл
1
Ой. Нет проблем на самом деле. Это просто ошибка веб-набора. В Safari и Chrome «реальная» высота по умолчанию составляет 100%, а не автоматически. Как бы мне обойти это тогда?
bjb568
4
@ Чувак, да, понятно. Он работает нормально в Firefox, но не Chrome или Safari. В соответствии со спецификацией SVG , Firefox представляется правильным; в то время как значение по умолчанию для элемента SVG widthи heightдля него составляет 100%, это не определение CSS, равное 100% (100% содержащего блока), а вместо этого 100% области просмотра, которая была определена на основе внутреннего соотношения сторон ( который вычисляется из viewBoxкогда это дается). Я еще не нашел решение этой проблемы, которое работает в Chrome / Safari.
Брайан Кэмпбелл
1
Это работает для меня. Сначала я создаю атрибут viewBox для элемента SVG и устанавливаю значение «0 0 [исходная ширина SVG] [исходная высота SVG]». Затем я изменяю атрибут ширины элемента SVG на «auto», а атрибут высоты на «100%». Контейнер также должен иметь определенную высоту. Это масштабирует вектор до 100% высоты контейнера, позволяя ширине плавать. Наконец, установите максимальную ширину CSS SVG на 100%, чтобы предотвратить перегрузку контейнера.
Райан Григгс
28

После примерно 48 часов исследований я в итоге сделал это, чтобы получить пропорциональное масштабирование:

ПРИМЕЧАНИЕ. Этот образец написан с использованием React. Если вы не используете это, измените материал дела верблюда обратно на дефисы (то есть: измените backgroundColorна background-colorи измените стиль Objectобратно на a String).

<div
  style={{
    backgroundColor: 'lightpink',
    resize: 'horizontal',
    overflow: 'hidden',
    width: '1000px',
    height: 'auto',
  }}
>
  <svg
    width="100%"
    viewBox="113 128 972 600"
    preserveAspectRatio="xMidYMid meet"
  >
    <g> ... </g>
  </svg>
</div>

Вот что происходит в приведенном выше примере кода:

Viewbox

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox

min-x, min-y, ширина и высота

т.е.: viewbox = "0 0 1000 1000"

Viewbox является важным атрибутом, потому что он в основном говорит SVG, какой размер рисовать и где. Если вы использовали CSS для создания SVG 1000x1000 px, но ваш viewbox был 2000x2000, вы увидите верхнюю левую четверть SVG.

Первые два числа, min-x и min-y, определяют, должен ли SVG быть смещен внутри окна просмотра.

Мой SVG должен сдвигаться вверх / вниз или влево / вправо

Изучите это: viewbox = "50 50 450 450"

Первые два числа будут сдвигать SVG влево на 50 пикселей и выше на 50 пикселей, а вторые два числа соответствуют размеру окна просмотра: 450x450 пикселей. Если ваш SVG имеет размер 500x500, но на нем есть дополнительные отступы, вы можете манипулировать этими числами, чтобы перемещать их внутри «окна просмотра».

Ваша цель на данный момент состоит в том, чтобы изменить один из этих номеров и посмотреть, что произойдет.

Вы также можете полностью опустить окно просмотра, но тогда ваш пробег будет варьироваться в зависимости от всех других настроек, которые у вас есть в данный момент. По моему опыту, вы столкнетесь с проблемами с сохранением соотношения сторон, потому что окно просмотра помогает определить соотношение сторон.

СОХРАНИТЬ АСПЕКТ

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio

Основываясь на моих исследованиях, существует множество различных настроек соотношения сторон, но по умолчанию они называются xMidYMid meet. Я положил это на себя, чтобы явно напомнить себе. xMidYMid meetпропорционально масштабируется в зависимости от средней точки X и Y. Это означает, что он остается в центре окна просмотра.

ШИРИНА

MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/width

Посмотрите на мой пример кода выше. Обратите внимание, как я установил только ширину, а не высоту. Я установил его на 100%, чтобы он заполнил контейнер, в котором он находится. Это то, что, вероятно, больше всего способствует ответу на этот вопрос переполнения стека.

Вы можете изменить его на любое значение пикселя, которое хотите, но я бы рекомендовал использовать 100%, как я, чтобы увеличить его до максимального размера, а затем управлять им с помощью CSS через родительский контейнер. Я рекомендую это, потому что вы получите «правильный» контроль. Вы можете использовать медиа-запросы, и вы можете контролировать размер без сумасшедшего JavaScript.

Масштабирование с помощью CSS

Посмотрите на мой пример кода выше снова. Обратите внимание, как у меня есть эти свойства:

resize: 'horizontal', // you can safely omit this
overflow: 'hidden',   // if you use resize, use this to fix weird scrollbar appearance
width: '1000px',
height: 'auto',

Это дополнительная информация, но она показывает, как разрешить пользователю изменять размер SVG, сохраняя при этом правильное соотношение сторон. Поскольку SVG поддерживает свое собственное соотношение сторон, вам нужно только изменить ширину в родительском контейнере, и она изменит размер по желанию.

Мы оставляем высоту в одиночестве и / или устанавливаем ее на авто, и мы контролируем изменение размера по ширине. Я выбрал ширину, потому что это часто более значимо из-за отзывчивых проектов.

Вот изображение этих настроек используется:

введите описание изображения здесь

Если вы прочитали каждое решение в этом вопросе и все еще не понимаете, что вам нужно, перейдите по этой ссылке здесь. Я нашел это очень полезным:

https://css-tricks.com/scale-svg/

Это огромная статья, но она разбивает практически все возможные способы манипулирования SVG, с или без CSS. Я рекомендую прочитать его, попивая кофе или выбор жидкости.

agm1984
источник
Похоже, это не работает для любого SVG. Если у вас нет контроля над источником SVG, этот метод завершается ошибкой, когда SVG имеет фиксированную ширину.
user48956
@ user48956 Вы всегда можете манипулировать им после факта с помощью JavaScript.
Эндрю
Да, вы всегда можете покопаться во внутренностях различных форматов файлов с помощью программирования - но вы надеетесь, что найдется метод, который работает для всех видов ресурсов (например, PNG) и не требует программирования на JavaScript.
user48956
21

Вы хотите сделать преобразование как таковое:

с помощью JavaScript:

document.getElementById(yourtarget).setAttribute("transform", "scale(2.0)");

С помощью CSS:

#yourtarget {
  transform:scale(2.0);
  -webkit-transform:scale(2.0);
}

Оберните свою страницу SVG в тег Group как таковой и нацелите его на манипулирование всей страницей:

<svg>
  <g id="yourtarget">
    your svg page
  </g>
</svg>

Примечание : шкала 1,0 составляет 100%

Гэри Хейс
источник
7
Хорошо. Я не хочу JS в этом. Есть ли способ сделать так, чтобы он соответствовал родителю?
bjb568
@bj setAttribute - это то же самое, что и <tag attribute = "value">
Джон Ктеджик
17

Пошарил и обнаружил, что этот CSS, похоже, содержит SVG в браузере Chrome до того момента, когда контейнер больше, чем изображение:

div.inserted-svg-logo svg { max-width:100%; }

Также, кажется, работает в FF + IE 11.

Kerry7777
источник
Это решило проблему для меня. Я только видел переполнение в iOS все же. Спасибо!
Эван Мэтсон
5
Использование обоих max-width: 100%и max-height: 100%заставит svg всегда масштабироваться до контейнера без переполнения и потери соотношения сторон.
Гэвин
2
@ Гавин max-height: 100%не работает для меня, решено с помощью vhвместо%
Павел
2

изменение файла SVG не было для меня справедливым решением, поэтому вместо этого я использовал относительные единицы CSS .

vh, vw, %Очень удобно. Я использовал CSS, height: 2.4vh;чтобы установить динамический размер моих SVG-изображений.

canbax
источник
1

Еще один простой способ

transform: scale(1.5);
Касим ШЕН
источник
0

Настройка атрибута currentScale работает в IE (я тестировал IE 11), но не в Chrome.

Фабиан Мадурай
источник