- Введение
- SVG viewport
- SVG viewBox
- Процесс взаимодействия viewport и viewBox
- Изменение масштаба с помощью viewBox
Введение
Изменение параметров viewBox – атрибута элемента SVG позволяет масштабировать, фрагментировать, перемещать исходное изображение вдоль осей координат. Но довольно часто возникают вопросы: “Почему, изменив параметры viewBox, я получаю совсем не то, что ожидал увидеть?”. Вместо увеличения картинки в 2 раза, она совсем пропадает с дисплея или сдвигается не в ту сторону и т.д. Чтобы разобраться в причинах этих “аномалий” рассмотрим подробно процессы взаимодействия областей просмотра элемента SVG и его параметра viewBox.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "//www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="400" height="400" version="1.1" viewBox="0 0 400 400" preserveAspectRatio="none" xmlns="//www.w3.org/2000/svg" style="border: 2px dashed blue;"> <!--colored circles in corners of the canvas --> <circle cx="55" cy="55" r="50" fill="rgba(20,255,24, 0.5)" stroke="rgba(6,90,6, 0.75)" stroke-width="2"/> <circle cx="350" cy="55" r="50" fill="rgba(57,65,212, 0.5)" stroke="rgba(26,31,167, 0.75)" stroke-width="2"/> <circle cx="350" cy="350" r="50" fill="rgba(212,30,75, 0.5)" stroke="rgba(212,30,75, 0.75)" stroke-width="2"/> <circle cx="55" cy="350" r="50" fill="rgba(255,221,0, 0.5)" stroke="rgba(169,146,0, 0.75)" stroke-width="2"/> <!--the red rectangle outside viewing area svg --> <rect x="390" y="165" width="100" height="100" fill="rgba(244,47,39, 0.6)" stroke="rgba(244,47,39, 0.75)" stroke-width="2"/> </svg> |
Лист.1
2. SVG viewport
В фрагменте кода (см. Лист.1) третья строка определяет прямоугольную область просмотра – SVG viewport и систему координат viewport coordinate system с началом координат (0,0) в левом верхнем углу, положительным направлением оси абцисс “X” – вправо и положительным направлением оси ординат “Y” – вниз. В нашем примере ширина прямоугольной области просмотра – width=”400px” и высота – height=”400px”. По умолчанию ед. измерения в пикселях и поэтому “px” можно не указывать. Также могут применяться и другие единицы измерения, например дюймы: <svg width=”20in” height=”20in” …>(см. Лист.2)
1 2 3 4 5 6 7 8 9 |
em The default font size - usually the height of a character. ex The height of the character x px Pixels pt Points (1 / 72 of an inch) pc Picas (1 / 6 of an inch) cm Centimeters mm Millimeters in Inches % percentages |
Лист.2
3. SVG viewBox
4-я строка кода см. Лист. 1 , – viewBox=”0 0 400 400″ – определяет пользовательскую область просмотра –User Space с пользовательской системой координат – User Coordinate system. Так как viewPort является предком для viewBox, то начало системы координат viewBox, по умолчанию, также как и системы координат viewPort находится в левом верхнем углу (0,0) и положительное направление оси “X” – будет также вправо, а оси “Y” – вниз.
Первые два числа ViewBox = “min-x” и “min-y” задают начало пользовательской системы координат, “width” и “height” – определяют ширину и высоту “пользовательской области просмотра” и одновременно отвечают за масштабирование изображения.
Четыре параметра viewBox разделяют пробелами или запятыми.
1 2 3 4 |
min-x - задаёт начало оси координат - X может принимать 0,(+) или (-) числовые значения. min-y - задаёт начало оси координат - Y может принимать 0,(+) или (-) числовые значения. width - ширина пользовательской области просмотра, принимает только (+) значения height - высота пользовательской области просмотра, принимает только (+) значения |
Лист.3
“Пользовательская область просмотра”, создаваемая параметром viewBox, является виртуальной, невидимой областью для пользователя и служит для трансформации изображения, получаемого из области просмотра SVG viewport.
Другими словами, при наличии в коде файла SVG объявления viewBox=”….”, всегда есть две области просмотра, каждая со своими осями и своим началом координат.
4. Процесс взаимодействия viewport и viewBox
Холст SVG документа имеет бесконечные размеры.
Viewport и viewBox – это две прямоугольные области просмотра, которые ограничены конечными значениями высоты и ширины, указанными в параметрах viewport и viewBox. При изменении параметров viewport и viewBox появляется возможность отобразить без искажений или трансформировать любой конкретный фрагмент холста SVG.
Далее в тексте и на рисунках для обозначения ширины и высоты приняты следующие сокращения:
- для области просмотра ” SVG viewport” – “SVG width” и “SVG height“
- для области просмотра “viewBox” – “viewBox width” и “viewBox height“
Рассмотрим пример, когда параметры этих областей просмотра совпадают. Всё, что находится вне области, ограниченной осями “SVG width” и “SVG height” не отображается.
Например: большая часть прямоугольника “5” красного цвета см. Лист.4 и Рис.1
1 |
<rect x="390" y="165" width="100" height="100" fill="rgba(244,47,39, 0.6)" stroke="rgba(244,47,39, 0.75)" stroke-width="2"/> |
Лист.4
не попадает в область просмотра, так как он имеет начало координат по оси Х=390px, ширина его 100px, поэтому от прямоугольника остается в видимой области по ширине только: 400px-390px=10px. Остальные 90px вне области видимости.
Вторая область – viewBox служит для трансформации векторной графики полученной от SVG viewport – первой области просмотра.
В процессе согласования – “by a negotiation process” сравниваются параметры двух областей просмотра: SVG viewport и viewBox. Если они полностью совпадают, как в нашем примере, то графика от viewBox без изменений передается обратно в первую область просмотра viewport см. Рис.1
Прерывистый голубой контур и квадратики показывают границы и область просмотра SVG viewport.
4а. Смещение начала координат viewBox по одной оси
Изменяя параметры viewBox: min-x, min-y, можно сместить начало пользовательских координат относительно начала координат SVG viewport.
viewBox=”70px, 0, 400px, 400px” см. Рис.2
На Рис.2 начало пользовательских координат сдвигается вправо на 70px, тем самым сдвигая вправо по оси абцисс всю прямоугольную область просмотра viewBox (400 x 400px). При этом происходит захват изображения фрагмента документа SVG, который находится под viewBox, а далее область просмотра viewBox, с захваченным фрагментом, обратно совмещается с неподвижной областью просмотра viewport с началом координат (0,0) в левом верхнем углу. Координаты фигур пересчитываются с учетом последнего сдвига на 70px влево. Формально получается, что в неподвижной области просмотра viewport, при применении viewBox, фрагмент документа SVG сдвинулся влево.
Поэтому в нашем примере на ширине 70px появляется, скрытая ранее, большая часть красного прямоугльника – 5, а зелёный и жёлтый круг обрезаются слева по ширине на 70px. см. Рис.3
Посмотреть, как это происходит можно на демо.
4б. Смещение начала координат viewBox по двум осям
Теперь переместим начало координат по двум осям сразу в точку (70,70):
viewBox=”70px, 70px, 400px, 400px”. Для наглядности добавим внизу еще один красный прямоугольник – (6). см.Рис.4
1 |
<rect x="160" y="390" width="100" height="100" fill="rgba(244,47,39, 0.6)" stroke="rgba(244,47,39, 0.75)" stroke-width="2"/> |
После переноса начала координат в область видимости viewBox попадает прямоугольный (400×400)px фрагмент SVG документа с отсчетом ширины и высоты от начала координат (70,70). Происходит захват изображения. Далее начало координат viewBox (70,70) совмещается с началом координат viewport (0,0). Координаты фигур пересчитываются.
Поэтому становятся полностью видны красные прямоугольники 5 и 6. Всё, что не попадает в эту область, отсекается. Например, часть площадей цветных окружностей 1,2 и 4.
Другими словами, перемещая начало координат viewBox вправо и вниз на 70px, в итоге получаем перемещение фрагмента документа SVG в области просмотра viewport влево и вверх.
5. Изменение масштаба с помощью viewBox
За масштаб фрагмента документа SVG отвечает пропорциональное соотношение ширин и высот соответственно двух областей просмотра: viewport и viewBox. Если соотношение сторон равны 1, то конечное изображение будет передано в масштабе 1:1, то есть без трансформации.
Если соотношение сторон будет отличаться от единицы, то масштаб будет меняться в сторону увеличения или уменьшения.
5.а Увеличение масштаба М2:1
1 2 |
<svg width="400" height="400" version="1.1" viewBox="0 0 200 200" preserveAspectRatio="none" |
Соотношение сторон областей просмотра, в этом примере, равно 400 / 200=2, поэтому масштаб фрагмента изображения досумента SVG будет М2:1.
Как происходит увеличение масштаба поясняют рисунки 7 и 8. Прямоугольная область просмотра viewBox захватывает фрагмент изображения (200 х 200)px.
При совмещении с первой областью просмотра происходит растягивание захваченного изображения до границ SVG viewport (400 x 400)px. Один пиксель viewBox занимает теперь два пикселя SVG viewport. Все размеры фигур пересчитываются умножением на х 2.
5.б Уменьшение масштаба М1:2
1 2 |
<svg width="400" height="400" version="1.1" viewBox="0 0 800 800" preserveAspectRatio="none" |
Соотношение сторон областей, в этом примере, равно 400 / 800=1/2, поэтому масштаб фрагмента изображения досумента SVG будет М1:2.
viewBox захватывает прямоугольный фрагмент (800 х 800)px, то есть всю область видимости SVG viewport (400 x 400)px и дополнительно по 400px справа и снизу от viewport.
При обратном совмещении, захваченного фрагмента изображения (800 x 800)px с областью видимости SVG viewport (400 x 400)px, происходит уменьшение масштаба изображения М1:2, так как 2 пикселя viewBox совмещаются c 1 пикселем SVG viewport.
⇚ Как добавить SVG в HTML5 страницу SVG marker ⇛
Пацан! Афигенно! Ты только болт на проект не клади, а ещё публикуйся на http://habrahabr.ru/ с линковками сюда. В общем ты делаешь серьёзное и важное дело – тебе бы как-то «обаблоситься» по этому направлению…
Спасибо, данный урок очень помог в понимании.
Народ, вы понимаете сколько нужно было читать доки чтобы написать такой концентрат. Спасибо тебе добрый человек.
Присоединяюсь к благодарностям и пожеланиям!
Ломал голову над viewBox, не понимал как работает, но после Вашей статьи все теперь ясно, гигантское спасибо!
Спасибо! Очень познавательно
Спасибо автору, годная статья! Мне понравилась.
Всё довольно подробно расписанно и разжёвано!
Вы сделали большую работу )
Великолепная статья! Все понял с первого раза! Автору огромное спасибо!