Масштабирование объекта SVG в HTML

246
06 июля 2018, 15:00

Подскажите, как правильно объявить svg объект, чтобы он занял все свободного пространство экрана и при этом не "вылезал" вниз. Например у меня есть svg:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="full" height="1088px" style="background:#FFFFFF" version="1.1" width="1088px"> 
  <defs> 
    <style type="text/css"> 
        .default_default { 
          fill: #E4801B; 
          stroke: #000000; 
          stroke-width: 1.0px; 
        } 
    </style> 
  </defs> 
  <g id="root" transform="translate(0,0)"> 
	  <g id="Auto" class="default_default" transform=" translate(0,0) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c0trumpet"/> 
		  </g> 
	  </g> 
	  <g id="Auto" class="default_default" transform=" translate(576,576) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c1trumpet"/> 
		  </g> 
	  </g> 
	  <!-- тут еще 14 групп с id="Auto"--> 
	  <g id="Auto" class="default_default" transform=" translate(960,960) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c15trumpet"/> 
		  </g> 
	  </g> 
  </g> 
</svg>

Auto.html выглядит следующим образом:

<!DOCTYPE html> 
<html lang="ru"> 
<head> 
    <meta charset="UTF-8"> 
    <title>test</title> 
</head> 
<body> 
    <div class="menu"> 
        <a href="Auto.html">Untitled</a> 
        <div> 
            <object id="AutoId" type="image/svg+xml" data="Auto.svg"></object> 
        </div> 
        <script type="text/javascript" src="Auto.js"></script> 
    </div> 
</body> 
</html>

Таким образом я получаю страницу, которая представлена на рисунке 1. Как видно, не вся svg поместилась на страницу. А хотелось бы получить результат как на второй картинке, т.е. уместить всю svg в область под Untitled так, чтобы вниз страница не прокручивалась.

Answer 1

Масштабирование SVG файла

  • Если вам нужно, чтобы svg изображение с размерами width="1088" и height="1088" занимало весь экран и не выходило за его рамки, то необходимо указывать ширину и высоту 100% в шапке svg файла - width="100%" height="100%" и добавить viewBox="0 0 1088 1088"
    • Для наглядности я добавил стиль - style="border:1px solid red;" - это будет красная рамка, которая чётко показывает границы SVG изображения.

Ниже код вашего svg файла с измененной шапкой, как написано выше:

<svg xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"   width="100%" height="100%" viewBox="0 0 1088 1088"  style="border:1px solid red;"> 
  <defs> 
    <style type="text/css"> 
        .default_default { 
          fill: #E4801B; 
          stroke: #000000; 
          stroke-width: 1.0px; 
        } 
    </style> 
  </defs> 
  <g id="root" transform="translate(0,0)"> 
	  <g id="Auto" class="default_default" transform=" translate(0,0) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c0trumpet" /> 
		  </g> 
	  </g> 
	  <g id="Auto" class="default_default" transform=" translate(576,576) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c1trumpet"/> 
		  </g> 
	  </g> 
	  <!-- тут еще 14 групп с id="Auto"--> 
	  <g id="Auto" class="default_default" transform=" translate(960,960) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c15trumpet"/> 
		  </g> 
	  </g> 
  </g> 
</svg>

Здесь в сниппете не видно, но если вы откроете этот файл локально на своем ПК, то будет заметно, что svg занимает весь экран без полос прокрутки.

Но изображение не прижато к левому углу дисплея. Это происходит, из-за того, что задан квадрат 1088х1088, а окно браузера прямоугольное.

  • Чтобы прижать изображение к левому верхнему углу, необходимо добавить ещё один параметр в шапку svg файла: preserveAspectRatio="xMinYMin meet"

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  width="100%" height="100%" 
viewBox="0 0 1088 1088" preserveAspectRatio="xMinYMin meet"   
style="border:1px solid red;" > 
  <defs> 
    <style type="text/css"> 
        .default_default { 
          fill: #E4801B; 
          stroke: #000000; 
          stroke-width: 1.0px; 
        } 
    </style> 
  </defs> 
  <g id="root" transform="translate(0,0)"> 
	  <g id="Auto" class="default_default" transform=" translate(0,0) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c0trumpet" /> 
		  </g> 
	  </g> 
	  <g id="Auto" class="default_default" transform=" translate(576,576) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c1trumpet"/> 
		  </g> 
	  </g> 
	  <!-- тут еще 14 групп с id="Auto"--> 
	  <g id="Auto" class="default_default" transform=" translate(960,960) rotate(0,32,32)"> 
		  <g id="layer0"> 
			<rect y="24" x="0" height="16" width="64" id="c15trumpet"/> 
		  </g> 
	  </g> 
  </g> 
</svg>

Оптимизация кода SVG

 <g id="root" transform="translate(0,0)">
      <g id="Auto" class="default_default" transform=" translate(0,0) rotate(0,32,32)">
          <g id="layer0">
            <rect y="24" x="0" height="16" width="64" id="c0trumpet"/>
          </g>
      </g>  
  • Код явно избыточен,- две пары групповых тегов <g> c ненужными идентификаторами Причем такой код будет повторятся много раз.
  • Команда rotate(0,32,32) лишняя, какой смысл поворачивать прямоугольник на нулевой угол?

  • от команды transform="translate(X Y)" тоже можно освободиться

Взамен можно объявить прямоугольник rect один раз в секции <defs> и затем его многократно клонировать с помощью команды <use> .

<defs> <rect id="rec" height="16" width="64" /> </defs> <use xlink:href="#rec" x="10" y="24" /> <use xlink:href="#rec" x="74" y="84" />

Ниже полный код вашего примера

<svg xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="full"  style="border:1px solid red" version="1.1" width="100%" height="100%" viewBox="0 0 1088 1088" preserveAspectRatio="xMinYMin meet" > 
  <defs> 
    <style type="text/css"> 
        #rec { 
          fill: #E4801B; 
          stroke: #000000; 
          stroke-width: 1.0px; 
        } 
    </style> 
  <rect id="rec"  height="16" width="64"  /> 
  </defs> 
   <use xlink:href="#rec" x="10" y="24" />  
   <use xlink:href="#rec" x="74" y="84" />  
   <use xlink:href="#rec" x="138" y="144" /> 
   <use xlink:href="#rec" x="202" y="204" /> 
   <use xlink:href="#rec" x="266" y="264" />  
   <use xlink:href="#rec" x="330" y="324" />  
   <use xlink:href="#rec" x="394" y="384" />   
   <use xlink:href="#rec" x="458" y="444" />  
   <use xlink:href="#rec" x="522" y="504" />  
   <use xlink:href="#rec" x="586" y="564" />  
   <use xlink:href="#rec" x="650" y="624" />  
   <use xlink:href="#rec" x="714" y="684" />  
   <use xlink:href="#rec" x="778" y="744" />  
   <use xlink:href="#rec" x="842" y="804" />  
   <use xlink:href="#rec" x="906" y="864" />  
   <use xlink:href="#rec" x="970" y="924" />  
   <use xlink:href="#rec" x="1034" y="984" />  
     
</svg>

за позиционирование элементов отвечают координаты X Y команды <use>

Повторюсь: Чтобы убедиться, что svg не выходит за рамки дисплея браузера (нет полос прокрутки) - скачайте файл и смотрите его на локальном ПК, без искажений масштабирования, которые вносит сниппет сайта.

Добавление SVG в HTML

Пока вы не набрались опыта работы с SVG, лучше использовать инлайн добавление в HTML.

Для этого оборачиваем svg код в <div id="container">

<style> 
.container { 
width:100%; 
height:100%; 
} 
</style> 
<div class="container" > 
<svg xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="full"  style="border:1px solid red" version="1.1" width="100%" height="100%" viewBox="0 0 1088 1088" preserveAspectRatio="xMinYMin meet" > 
  <defs> 
    <style type="text/css"> 
        #rec { 
          fill: #E4801B; 
          stroke: #000000; 
          stroke-width: 1.0px; 
        } 
    </style> 
  <rect id="rec"  height="16" width="64"  /> 
  </defs> 
   <use xlink:href="#rec" x="10" y="24" />  
   <use xlink:href="#rec" x="74" y="84" />  
   <use xlink:href="#rec" x="138" y="144" /> 
   <use xlink:href="#rec" x="202" y="204" /> 
   <use xlink:href="#rec" x="266" y="264" />  
   <use xlink:href="#rec" x="330" y="324" />  
   <use xlink:href="#rec" x="394" y="384" />   
   <use xlink:href="#rec" x="458" y="444" />  
   <use xlink:href="#rec" x="522" y="504" />  
   <use xlink:href="#rec" x="586" y="564" />  
   <use xlink:href="#rec" x="650" y="624" />  
   <use xlink:href="#rec" x="714" y="684" />  
   <use xlink:href="#rec" x="778" y="744" />  
   <use xlink:href="#rec" x="842" y="804" />  
   <use xlink:href="#rec" x="906" y="864" />  
   <use xlink:href="#rec" x="970" y="924" />  
   <use xlink:href="#rec" x="1034" y="984" />  
     
</svg> 
</div>

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

Answer 2

Возможно кому-то пригодится еще один вариант решения. svg шапка:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="full" height="100%" style="background:#31C184" version="1.1" viewBox="0 0 1088 1088" width="100%">

И html с js

window.onload = function() { 
    svgDoc = document.getElementById("AutoId").contentDocument; 
    var timer = setInterval(anim, 100); 
    var timerPost = setInterval(setPost, 100); 
    initClick(); 
    updateSize(); 
} 
 
window.onresize = updateSize; 
 
function updateSize() { 
    vpW = document.getElementsByClassName('main')[0].clientWidth; 
    vpH = document.getElementsByClassName('main')[0].clientHeight; 
    //imgW = document.getElementsByClassName('box content')[0].clientWidth; 
    //imgH = document.getElementsByClassName('box content')[0].clientHeight; 
    imgW = 1088; 
    imgH = 1088; 
    //alert(vpW + ':' + vpH + ' = ' + vpW/vpH + '      ' + imgW + ':' + imgH + ' = ' + imgW/imgH); 
 
    if(vpW/vpH < imgW/imgH) { 
        for(var i = 0; i < 2; i++) { 
            document.getElementsByClassName('horizontalbar')[i].style.height = (vpH - vpW)/2 + 'px'; 
            document.getElementsByClassName('box sidebar')[i].style.width = '0px'; 
        } 
    } else { 
        for(var i = 0; i < 2; i++) { 
            document.getElementsByClassName('box sidebar')[i].style.width = (vpW - vpH)/2 + 'px'; 
            document.getElementsByClassName('horizontalbar')[i].style.height = '0px' 
        } 
    } 
}
<!DOCTYPE html> 
<html lang="ru"> 
<head> 
    <meta charset="UTF-8"> 
    <title>testPrj</title> 
    <style> 
        .wrapper { 
          height: 100%; 
          display: table; 
          width: 100%; 
        } 
 
        .header { 
          display: table-row; 
          height: 1px; 
        } 
 
        .main { 
          height: 100%; 
          display: table; 
          width: 100%; 
        } 
 
        .horizontalbar { 
          display: table-row; 
          height: 0px; 
        } 
 
        .box { 
          display: table-cell; 
        } 
 
        .sidebar { 
          width: 0px; 
        } 
 
        .content { 
          height: 100%; 
        } 
 
        .content iframe { 
          width: 100%; 
          height: 100%; 
          border: none; 
          margin: 0; 
          padding: 0; 
          display: block; 
        } 
 
        .footer { 
          display: table-row; 
          height:1px; 
        } 
 
        /* Basic Style*/ 
        * { margin:0; padding:0;} 
        html, body { 
          height: 100%; 
        } 
    </style> 
</head> 
<body bgcolor="#ffff00"> 
    <div class="wrapper"> 
      <div class="header"> 
        <h1>Header</h1> 
        <button onclick='location.href="Auto.html"'>Auto</button> 
        <button onclick='location.href="Auto1.html"'>Auto1</button> 
      </div> 
 
      <div class="main"> 
        <div class="horizontalbar"></div> 
        <div class="box sidebar"></div> 
        <div class="box content"> 
          <iframe frameborder="0" marginwidth="0" marginheight="0" src="Auto.svg" id="AutoId"></iframe> 
        </div> 
        <div class="box sidebar"></div> 
        <div class="horizontalbar"></div> 
      </div> 
      <div class="footer">Text. Text</div> 
    </div> 
    <script type="text/javascript" src="Auto.js"></script> 
</body> 
</html>

Адекватно работает только для квадратных svg.

READ ALSO
Как сделать вывод имя пользователя на странице &ldquo;Спасибо&rdquo;?

Как сделать вывод имя пользователя на странице “Спасибо”?

В корне сайта на одном уровне находится главная страница: indexhtml, страница благодарности после отправки формы:thank-you-page

250
Установка границ для блока

Установка границ для блока

Осваиваю bootstrap и столкнулся с проблемойМне нужно для моих блоков (левый,правый,нижний) установить видимые границы, чтобы было четкое разделение...

233
PageSpeed Insights ругается на оптимизацию, не могу найти причину такого показателя

PageSpeed Insights ругается на оптимизацию, не могу найти причину такого показателя

PageSpeed Insights Ругается на ужасный показатель, причину того найти не могу, сжал изображения насколько это было возможно с 50 до 9мб, убрал лишний...

220
jquery Отрицание

jquery Отрицание

Конструкция, которая скрывает все элементы, у которых checkbox:checked

211