Як я можу зробити масштаб SVG з його батьківським контейнером?


235

Я хочу мати вбудовану шкалу вмісту елемента SVG, коли розмір не є власним. Звичайно, я міг би мати його як окремий файл і масштабувати його так.

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

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

Однак я хочу додати додаткові стилі до SVG через CSS, тому зв'язування зовнішнього не є варіантом. Як зробити вбудовану шкалу SVG?


2
спробуйте прецеденти у ширині та висоті svg.
ncm

@ncm Як би це було зроблено з JS?
Мауг каже, що повернемо Моніку

Відповіді:


457

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

Наприклад, якщо у вас є наступне:

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

Він буде відображатися у вигляді трикутника 10 пікселів на 20 пікселів:

Трикутник 10х20

Якщо ви встановите лише ширину та висоту, це змінить розмір елемента SVG, але не масштабує трикутник:

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

Трикутник 10х20

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

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

Трикутник 100х50

Якщо ви хочете масштабувати його до ширини вікна перегляду HTML:

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

Трикутник 300х150

Зауважте, що за замовчуванням співвідношення сторін зберігається. Отже, якщо ви вказали, що елемент повинен мати ширину 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>

Трикутник 100х50

Якщо ви дійсно хочете, щоб він розтягувався горизонтально, відключіть збереження співвідношення сторін за допомогою 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>

Трикутник 300х50

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


1
Як вам зробити не тільки viewBox зберігатиAspectRatio, але і основне поле? Я хочу ширину: 100%; висота: авто для нього.
bjb568

1
@Dude: Я думаю, що приклад з width="100%"вказаною висотою і без вказаної висоти робить те, що ти хочеш. Я додав зображення для демонстрації. Він має 100% ширину і пропорційно збільшує висоту. Якщо це не те, що ви шукаєте, можете спробувати уточнити, що ви мали на увазі?
Брайан Кемпбелл

1
Ой. Фактично немає проблем. Це просто помилка в веб-кайті. У Safari та Chrome "справжня" висота за замовчуванням становить 100%, а не автоматична. Як я тоді обійшов би це?
bjb568

4
@ Чувак Ах, так, я бачу. У Firefox він працює добре, але немає Chrome або Safari. Відповідно до специфікації SVG , здається, що Firefox є правильним; в той час як значення за замовчуванням widthі heightдля елемента SVG становить 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назад до 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>

Ось що відбувається у наведеному вище прикладі коду:

ПІДГОТОВКА

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, але у вашому вікні перегляду 2000x2000, ви побачите верхню ліву чверть свого SVG.

Перші два числа, min-x та min-y, визначають, чи слід SVG змістити всередині вікна перегляду.

Мій SVG повинен зміщуватися вгору / вниз або вліво / вправо

Вивчіть це: viewbox = "50 50 450 450"

Перші два номери змінять ваш SVG вліво на 50 пікселів і вгору на 50 пікселів, а другі два числа - розмір вікна перегляду: 450x450 пікселів. Якщо ваш SVG розміром 500x500, але на ньому є додаткові накладки, ви можете маніпулювати цими номерами, щоб перемістити його всередині "viewbox".

Ваша мета на даний момент - змінити одне з цих чисел і подивитися, що відбувається.

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

ЗБЕРІГАЙТЕ АСПЕКТНИЙ РАЙОН

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 або без нього. Рекомендую прочитати його, недбало пивши каву або вибираючи вибрані рідини.


Схоже, це не працює для будь-якого 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 у тег групи як такий і націліть на неї, щоб маніпулювати цілою сторінкою:

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

Примітка : Шкала 1,0 становить 100%


7
Гаразд. Я не хочу в цьому JS. Чи є спосіб перетворити його на придатний батьків?
bjb568

@bj setAttribute - це те саме, що <tag attribute = "value">
John ktejik

17

Збільшившись і знайшовшись, цей CSS, здається, містить SVG у браузері Chrome аж до того, що контейнер більший за зображення:

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

Також, здається, працює у FF + IE 11.


Це вирішило для мене питання. Я бачив лише переповнення в iOS. Дякую!
Еван Маттсон

5
Використання обох max-width: 100%і max-height: 100%зробить SVG завжди масштабуванням до контейнера, не переповнюючи і не втрачаючи співвідношення сторін.
Гевін

2
@Gavin max-height: 100%для мене не працює, вирішено за допомогою vhзамість%
Павло

2

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

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



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.