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

Кажется, это глупый вопрос и, возможно, обман, но на какое-то время я не нашел подходящего решения, поэтому, наконец, осмелюсь спросить.

Я хочу разместить элемент <svg> внутри html-документа и выполнить следующие требования:

  • Изображение помещается как элемент <svg> html5, а не внешний svg файл. (На самом деле, я хочу динамически генерировать его с помощью D3.js.)
  • Изображение помещается в центр экрана, как по вертикали, так и по горизонтали.
  • Фактический размер изображения не должен превышать предопределенное значение (например, 15cm × 15cm).
  • Если текущая ширина экрана или высота меньше, чем 15cm, изображение следует масштабировать (сохраняя пропорции) таким образом, чтобы оно соответствовало экрану. Никакие части изображения не должны быть обрезаны. Изображение должно быть размещено в центре.

В основном те же требования, что описаны в в этой статье. В нем говорится, что я должен использовать preserveAspectRatio="xMidYMid", но не дает никакого примера, как это сделать и как он соответствует другим трюкам, описанным в статье. В этой статье предлагается preserveAspectRatio="xMidYMid meet", но снова я не смог воспроизвести приведенные здесь примеры для удовлетворения всех моих требований.

Мой текущий код похож на этот, но он не подходит по высоте и не центрируется по вертикали.

.svg-container {
  height:100%;
  width:100%;
  max-height:15cm;
  max-width:15cm;
  margin: 0 auto;
}
<div class="svg-container">  
<svg id="picture" preserveAspectRatio="xMidYMid meet" viewBox="0 0 100 100">
  <circle cx=50 cy=50 r=50></circle>
</svg>
</div>

Ответ 1

Следующее работает, если соотношение сторон SVG задано. Если соотношение сторон SVG динамическое, вы должны использовать JavaScript, я считаю.

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

Фокус в том, что размеры SVG заданы относительно ширины или высоты экрана, в зависимости от того, что меньше всего. Это означает, что даже если мы установим его как 100vmin, SVG гарантированно будет соответствовать экрану (но едва). Чтобы обеспечить максимальные размеры, старый добрый max-width и max-height, в точности так, как они предназначены для использования.

html, body {
  /* ensure that all of the viewport is used */
  width: 100%;
  height: 100%;
  /* ensure that no scrollbars appear */
  margin: 0;
  padding: 0;
  
  /* center SVG horizontally and vertically */
  display: flex;
  align-items: center;
  justify-content: center;
}

#picture {
  /* ensure 1:1 aspect ratio, tweak 50 to make SVG larger */
  width: 50vmin;
  height: 50vmin;  
  /* set some maximum size (width and height need to match
   * aspect ratio, 1:1 in this case */
  max-width: 200px;
  max-height: 200px;
}
<svg id="picture" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="50"></circle>
</svg>

Ответ 2

Попробуйте этот css:

#picture {
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  position: absolute;
  max-height:15cm;
  max-width:15cm;
  width: 80%;
  height: 80%;
}

вот результат: https://jsfiddle.net/twe9jfkf/

это то, чего вы пытаетесь достичь?

Ответ 3

Вместо css вы можете попробовать использовать svg width/height и viewBox, вычисленный с помощью getBBox() Ниже приведен базовый пример:

<!DOCTYPE HTML>

<html>

<body>
<svg>
  <circle cx=50 cy=50 r=50 fill=red />
</svg>

<script>
//--onload, onresize----
function sizeSVG()
{
	var mySVG=document.getElementsByTagName("svg")[0]

  	var svgW=window.innerWidth
	var svgH=window.innerHeight

    var bb=mySVG.getBBox()
	var bbx=bb.x
	var bby=bb.y
	var bbw=bb.width
	var bbh=bb.height

    mySVG.setAttribute("viewBox",bbx+" "+bby+" "+bbw+" "+bbh )
    mySVG.setAttribute("width",svgW)
    mySVG.setAttribute("height",svgH)
}

document.addEventListener("onload",sizeSVG(),false)
window.onresize=sizeSVG
</script>

</body>

</html>

Ответ 4

Решение flexbox было бы моим первым выбором. Поскольку кто-то еще ответил с этой идеей, я придумал этот подход.

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

body {
  height: 100vh;
  margin: 0;
}

svg#picture {
  max-height: 15cm;
  max-width: 15cm;
  height:100%;
  width:100%;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  margin:auto;
}
<svg id="picture" preserveAspectRatio="xMidYMid meet" viewBox="0 0 100 100">
  <circle cx=50 cy=50 r=50></circle>
</svg>

Ответ 5

Вы пытались добавить изображение в качестве фона в свой svg-контейнер?

.svg-container {
  height:100%;
  width:100%;
  max-height:15cm;
  max-width:15cm;
  margin: 0 auto;
  background-image:url('yourSVG.svg');
  background-repeat: no-repeat;
  background-size: contain;
}

Ответ 6

Вы все еще хотите вертикальную вертикаль? посмотрите это

.vertical-align {
	height:1000px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.svg-container {
  	max-height:15cm;
  	max-width:15cm;
	height: 100%;
	width: 100%;
}
<div class="vertical-align">
	<div class="svg-container">  
	<svg id="picture" preserveAspectRatio="xMidYMid meet" viewBox="0 0 100 100">
	  <circle cx=50 cy=50 r=50></circle>
	</svg>
	</div>
</div>