【发布时间】:2013-12-10 21:13:30
【问题描述】:
我正在尝试使用 preserveAspectRatio="xMidYMid meet" 缩放 SVG 图像以适合其容器,这是默认设置,但为了清楚起见,我还是指定了它。使用下面指定的 CSS 和 SVG,缩放就像我在 Chrome 中想要的那样工作。但是,在 IE 和 Firefox 中,问题是多边形以保留的纵横比缩放,但背景不是。无论容器的纵横比如何,背景仍会填充整个容器。在下面的 JSFiddle 或代码中,容器的背景应该是绿色的,图像的背景应该是灰色的,灰色部分是包围蓝色多边形所有四个角的正方形,因为蓝色多边形的高度相同和宽度为正方形viewBox。
换句话说,如果容器的高度 > 宽度,我希望在灰色/蓝色 SVG 图像的上方和下方看到绿色,如果容器的宽度 > 高度,我希望在灰色/蓝色的每一侧看到绿色SVG 图像。
有什么想法可以让它在所有支持 SVG 的浏览器中看起来像我想要的那样吗?
<!DOCTYPE html>
<html lang="en">
<head>
<style>
html, body{
height: 100%;
margin: 0;
}
#container {
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
width: 80%;
height: 80%;
margin: auto;
border: 5px solid black;
background-color: green;
}
#testSVG{
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
max-width: 100%;
max-height: 100%;
margin: auto;
background-color: gray;
}
</style>
<title>Scratch Pad</title>
</head>
<body>
<div id="container">
<svg
xmlns="http://www.w3.org/2000/svg"
version="1.1"
id="testSVG"
viewBox="0 0 300 300"
preserveAspectRatio="xMidYMid meet"
width="5000"
height="5000">
<polygon points="150,0 300,150 150,300 0,150" style="fill:blue;" />
</svg>
<!--
<img id="testSVG" src="test.svg"/>
-->
</div>
</body>
</html>
我会尝试预测人们可能会提出的一些问题:
问:为什么要使用 CSS 而不是仅仅更改 SVG 绘图?
答:我打算不仅用border-radius设置背景,还用border-radius设置边框,也许是阴影,也许是背景纹理,并使用:hover动态更改它们, :focus、:active 伪类,这些都是我在 CSS 中知道如何做,但在 SVG 中不知道如何做的事情。此外,我必须为旧浏览器提供 PNG 后备,如果我将背景、边框等作为图像本身的一部分,这意味着我将需要多个版本的 PNG,具体取决于应用了哪些伪类.由于这些原因,我更喜欢使用 CSS 边框和背景,而不是添加额外的 SVG 元素。
问:为什么要使用绝对定位来居中#testSVG? xMidYMid不应该帮你定位吗?
答:我也是这么想的,但事实并非如此。在没有绝对定位和margin: auto 的情况下,Chrome 将图像绘制在容器的左上角,然后在调整容器大小时出现错误的缩放。
问:当您通过 <img> 标记引用 SVG 图像而不是将 SVG 内联时,您是否发现了不同的行为?
答:是的。当我通过<img> 标签引用SVG 时,IE 不会保留图像的纵横比,除非我在<svg> 元素中使用100% 的width 和height 属性,但在这种情况下,如果容器的高度 > 宽度,Chrome 只会显示绿色背景,而不是容器的宽度 > 高度。在这两种情况下,IE 都不会显示绿色背景。
问:为什么要为svg 元素的width 和height 属性使用如此大的值?
答:使用指定的width 和height,浏览器似乎很乐意缩小图像以填充容器,但拒绝放大图像以填充容器。 (这不是meet 在preserveAspectRatio 属性中的用途吗?!)如果没有指定width 和height(即使用100% 的默认值),Chrome 在纵向和纵向表现出不同的行为。景观,如上一个答案中所述。至少以我目前的方式,它在一个浏览器中的工作方式与我想要的完全一样......
问:我想我可以让它像你想要的那样工作,但是我需要将图像包装在一个额外的非语义元素中。可以吗?
答:是的!我支持简单且纯语义的 HTML 的驱动,但迂腐的优先级应该始终低于实用性和功能性。
那么,我有什么想法可以让它在其他浏览器中像我想要的那样工作吗?
【问题讨论】:
-
AFAIK,它并没有真正定义像 background-color 这样的 HTML 样式属性如何应用于 SVG 对象。因此,浏览器彼此不一致也就不足为奇了。
<rect width="100%" height="100%"/>技术是我认为解决您的问题的唯一跨浏览器解决方案。 -
从根本上说,这不是如何应用样式属性的问题,而是如何计算包含图像的框的尺寸的问题。这应该包含在规范中:w3.org/TR/CSS2/visudet.html(第 10.3.2、10.4、10.6.2 和 10.7 节)。 Chrome 在计算盒子尺寸时选择尊重图像的“内在纵横比”,因此它会将盒子缩小到满足最大宽度和最大高度约束并适应纵横比所需的程度。 IE 和 Firefox 计算框尺寸时会忽略纵横比。
-
对于 SVG viewBox 属性是否构成“内在比率”,可能存在不同意见。我(和 Chrome 开发人员,显然)认为应该这样做。但是,我可以看到一个论点,即“preserveAspectRatio”属性指定允许忽略 viewBox 纵横比的行为。
标签: html css google-chrome svg