具有viewBox和宽度的SVG在IE中未正确缩放高度

时间:2014-10-09 05:35:52

标签: javascript html css svg

我正在尝试使用viewBox属性构建内联SVG,但没有明确的width或height属性。我正在使用CSS将SVG的宽度设置为100%。这应该让SVG缩放到它的包装容器,保持viewBox设置的宽高比。在Chrome和Firefox中,这非常有效!

这是我正在谈论的最小代码示例: http://codepen.io/pcorey/pen/amkGl

HTML:

<div>
  <svg viewBox="0 0 100 10">
    <text x="1" y="9">hello</text>
  </svg>
</div>

CSS:

div {
  width: 400px;
}

svg {
  width: 100%;
  max-height: 100%;
  outline: 1px solid tomato;
}

text {
  font-size: 10px;
}

viewBox是100x10。外部div设置为400px宽度。这意味着SVG的高度应该是(并且在Chrome / Firefox中)40px。但是,在IE 11中,宽度总是150px(即使div的宽度超过1500px ......)

有没有一种很好的方法来解决这个问题?为什么IE无法正确处理未知高度?我可以使用“intrinsic aspect ratio”技巧,但这非常难看,需要另一个DOM元素,并且每次包装器调整大小时都要求我重新计算padding-top。

有关我为什么要这样做的更多信息,我写了一篇关于它的快速博客文章:http://1pxsolidtomato.com/2014/10/08/quest-for-scalable-svg-text/

感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

应该适用于所有浏览器的一种解决方法是将空白图像添加到SVG所在的容器中,该容器与SVG具有相同的尺寸:

&#13;
&#13;
.wrap {
  position: relative;
}
img {
  width: 100%;
  height: auto;
}
.viz {
  position: absolute;
  top: 0;
  left: 0;
}
&#13;
<div class="wrap">
  <img src="img/blank.png" />
  <div class="viz">
    <svg preserveAspectRatio="xMinYMin slice" viewBox="0 0 1000 600"></svg>               
  </div>
</div>
&#13;
&#13;
&#13;

在这种情况下,您的图片应具有1000px到600px的自然尺寸并且是透明的(或与.wrap容器的背景相匹配)。这将适合svg所在容器的大小。 .viz元素的绝对位置将允许它坐在图像的顶部,利用它的高度,所以没有任何东西被切断。

答案 1 :(得分:3)

如果您没有放置一定的高度和宽度,某些浏览器(IE和Safari)将使用SVG的默认大小。这就是这里发生的事情。你是对的,“内在的方面比例”需要另一个Dom和css,如果我们能克服这个问题会很好。

有一个解决方案,你可以计算并将正确的高度放到padding-bottom,这将给你想要的正确的“未知高度”。 您可以在此处查看完整的解决方案: http://codepen.io/tomkarachristos/pen/GZPbgZ

<!--
xMidYMin: Align the midpoint X value of the element's viewBox with the midpoint X value of the viewport.
slice : the entire viewport is covered by the viewBox and the viewBox is scaled down as much as possible,
height: if you dont set >= 1px some browsers will not render anything.
-->
<div>
    <svg viewBox="0 0 100 10" preserveAspectRatio="xMidYMin slice"
         width="100%" style="height: 1px;overflow: visible;
         /*without js:padding-bottom:55%*/"><text>hello</text>
  </svg>
    <svg viewBox="0 0 100 10" preserveAspectRatio="xMidYMin slice"
         width="100%" style="height: 1px;overflow: visible;"><text>Age</text>
  </svg>
</div>

和javascript:

/*
Here we do the hack.
With the math type: percent * height/width
we are adjust the total height of an element who is depend in width using the padding-bottom.
You can put an inline padding-bottom if you want in html.
*/

$(function() {
  $('svg').each(function() {
    var svg = $(this);
    var text = svg.find('text');
    var bbox = text.get(0).getBBox();
    //the hack
    var calcString = "calc(100% * " + bbox.height/bbox.width + ")";
    svg.css("padding-bottom",calcString);

    svg.get(0).setAttribute('viewBox',
                           [bbox.x,
                            bbox.y,
                            bbox.width,
                            bbox.height].join(' '));
  });
});