Javascript 带有 viewBox 和宽度的 SVG 在 IE 中没有正确缩放高度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26271034/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:38:50  来源:igfitidea点击:

SVG with viewBox and width is not scaling height correctly in IE

javascripthtmlcsssvg

提问by pcorey

I'm trying to construct inline SVGs with viewBox attributes, but no explicit width or height attributes. I'm setting the SVG's width to 100% using CSS. This should let the SVG scale to its wrapping container, maintaining the aspect ratio set up by the viewBox. In Chrome and Firefox, this works perfectly!

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

Here's a minimal codepen example of what I'm talking about: http://codepen.io/pcorey/pen/amkGl

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

HTML:

HTML:

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

CSS:

CSS:

div {
  width: 400px;
}

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

text {
  font-size: 10px;
}

The viewBox is 100x10. The outer div is set to have a 400px width. That means that the SVG's height should be (and is in Chrome/Firefox) 40px. BUT, in IE 11, the width is ALWAYS 150px (even when the div's width exceeds 1500px...)

视图框是 100x10。外部 div 设置为 400px 宽度。这意味着 SVG 的高度应该是(在 Chrome/Firefox 中)40px。但是,在 IE 11 中,宽度始终为 150 像素(即使 div 的宽度超过 1500 像素...)

Is there a nice way to fix this in IE? Why can't IE handle the unknown height correctly? I can use the "intrinsic aspect ratio" trick, but that is super ugly, requires another DOM element, and requires that I recompute the padding-top every time the wrapper resizes.

在 IE 中是否有解决此问题的好方法?为什么 IE 不能正确处理未知高度?我可以使用“内在纵横比”技巧,但这非常难看,需要另一个 DOM 元素,并且需要在每次调整包装器大小时重新计算 padding-top。

For more info on why I want to do this, I wrote a quick blog post about it: http://1pxsolidtomato.com/2014/10/08/quest-for-scalable-svg-text/

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

Thanks for the help!

谢谢您的帮助!

回答by Taylor Plante

One workaround that should work in all browsers is to add a blank image to the container your SVG sits inside, which has the same dimensions as your SVG:

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

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

In this case, your image should have natural dimensions of 1000px by 600px and be transparent (or matching the background of your .wrap container). This will appropriate the size of the container the svg sits inside. The absolute position of the .viz element will allow it to sit on top of the image, utilizing it's height so nothing gets cut off.

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

回答by Thomas Karachristos

Some browsers(IE and safari) will be use a default size to SVG if you don't put a certain height and width. That what is happening here. You are right, the "intrinsic aspect ration" is requiring another Dom and css and will be nice if we can overcame this.

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

There is a solution to this, you can calculate and put the right height to padding-bottom and this will give the right "unknown height" you want. You can see a full solution here: http://codepen.io/tomkarachristos/pen/GZPbgZ

有一个解决方案,您可以计算并为 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>

and javascript:

和 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(' '));
  });
});