【问题标题】:Place square svg to the center of the screen, scale it to fit the screen's width and height with some constraints将方形 svg 放置到屏幕的中心,将其缩放以适应屏幕的宽度和高度,并带有一些约束
【发布时间】:2017-03-03 23:41:34
【问题描述】:

这似乎是一个愚蠢的问题,可能是一个骗局,但我一时找不到好的解决方案,所以终于敢问了。

我想在 html 文档中放置一个<svg> 元素并满足以下要求:

  1. 图像被放置为<svg> html5 元素,而不是外部svg 文件。 (其实我是想用D3.js动态生成。)
  2. 图像放置在屏幕的中心,垂直和水平。
  3. 图片的实际大小不应超过某个预定义的值(如15cm × 15cm)。
  4. 如果当前屏幕的宽度或高度小于15cm,则应缩放图像(保持纵横比)使其适合屏幕。不应剪裁图像的任何部分。图片应放在中间。

this article 中描述的要求基本相同。它说我应该使用preserveAspectRatio="xMidYMid",但没有给出如何使用它以及它如何对应于文章中描述的其他技巧的示例。 This article 建议 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>

【问题讨论】:

  • 你事先知道长宽比吗?也就是说,SVG 的viewBox 是给定的吗?

标签: html css svg


【解决方案1】:

如果 SVG 的纵横比是给定的,则以下方法有效。如果 SVG 的纵横比是动态的,我相信你必须使用 JavaScript。

这个 sn-p 在现代浏览器中工作,并充分利用了相对较新的 vmin viewport-percentage length。浏览器支持是pretty good。对于水平和垂直居中,利用flexbox 布局模式。同样,浏览器支持是pretty good

诀窍在于 SVG 的尺寸是相对于屏幕的宽度或高度设置的,以最小者为准。这意味着即使我们将其设置为100vmin,SVG 也能保证适合屏幕(但几乎没有)。为了强制实现最大尺寸,使用了旧的 max-widthmax-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>

【讨论】:

  • 谢谢,不知道vminflex
  • 如果svg图像上方有另一个div,如何处理?如何使这两个项目居中并保持响应?
  • 在这种情况下,@smartmouse,我建议使用 flexbox,它现在已被广泛支持。 display: flex; flex-direction: column; justify-content: center; align-items: center; 在身体上应该可以解决问题。`
  • 感谢您的回复。我确实在这里提出了自己的问题:stackoverflow.com/questions/56890448/…
【解决方案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/

这是你想要达到的目标吗?

【讨论】:

  • 这不会强制 SVG 元素具有给定的纵横比。尽管无论如何都会缩放 SVG 的内容,但默认情况下会保留纵横比,因此它仍然有效。整洁!
【解决方案3】:

您可能想尝试使用 svg 的宽度/高度和通过 getBBox() 计算的 viewBox 而不是 css 一个基本的例子如下所示:

<!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>

【讨论】:

  • 谢谢。我尝试了这种方法并且它有效。还是希望能找到一些纯css的解决方案(我以前相信是用css就能解决的简单问题)。
【解决方案4】:

flexbox 解决方案是我的首选。 由于其他人已经回答了这个想法,我想出了这种不同的方法。

基本上它是absolute centering technique 并依靠绝对位置和自动边距使元素居中。

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】:

    您仍然想要垂直对齐?看看这个

    .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>

    【讨论】:

      【解决方案6】:

      您是否尝试将图像作为背景添加到您的 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;
      }
      

      【讨论】:

      • 谢谢!我希望将我的 svg 放置为 &lt;svg&gt; 元素(实际上,我将使用 D3.js 生成图像),而不是嵌入外部文件,所以这对我不起作用。
      • 我明白了……是一个有趣的问题。期待解决方案。
      猜你喜欢
      • 2015-10-03
      • 1970-01-01
      • 2019-11-19
      • 1970-01-01
      • 2023-04-04
      • 2016-01-17
      • 1970-01-01
      • 2014-01-18
      • 2014-03-15
      相关资源
      最近更新 更多