如何缩放SVG

以下是Amelia Bellamy-Royds的来宾帖子。 作为SVG Essentials的合著者和即将出版的《 将SVG与CSS3和HTML5结合使用》的作者,Amelia在SVG方面拥有丰富的经验。 我和Amelia都将在即将到来的RWD峰会上就SVG发表演讲! 在这里,她分享了扩展SVG的史诗指南,涵盖了您可能要执行的所有方法。 它几乎不像缩放栅格图形那样简单,但是那样很好,因为它带来了有趣的可能性。

您已做出决定。 您终于要做到了。 今年,您将开始在Web设计中使用SVG 。 您在Inkscape中创建了精美的标题徽标,然后将其吐出的SVG代码复制并粘贴到WordPress标题文件中。 当然,您不会因为总是使用响应式设计而放弃去年的分辨率,因此您设置svg.banner { width: 100%; height: auto; } svg.banner { width: 100%; height: auto; } svg.banner { width: 100%; height: auto; } ,并认为您已设置好。

除非您在测试浏览器中打开网页,然后发现其中一些在图像的上方和下方都留有巨大的空白块,而另一些则将其裁剪得太短。

SVG代表可缩放矢量图形。 因此,缩放SVG应该很容易,对吧? SVG倡导者一直以来都在说SVG在任何大小上看起来都不错吗? 是的,但事实并非如此。 SVG在任何规模上都看起来不错,但是它可以以多种不同的方式进行扩展,以至于它只能按照您想要的方式运行,这会使SVG初学者感到困惑。 浏览器只是最近才开始采用标准方法来调整嵌入式SVG内容的大小,这无济于事。

SVG不是(只是)图像

缩放SVG如此困难的部分原因是因为我们对图像如何缩放有一定的了解,并且SVG的行为方式不同。

JPG,PNG和GIF之类的光栅图像具有明确定义的尺寸。 图像文件描述了浏览器应如何在一定像素宽和一定像素高的网格中着色。 一个重要的副作用是,光栅图像具有明确定义的宽高比宽高比

您可以强制浏览器以不同于其固有高度和宽度的大小来绘制光栅图像,但是如果将其强制为不同的宽高比,则事情将变得失真。 出于这个原因,自网络早期以来,就支持auto缩放图像:设置高度宽度,然后浏览器调整其他尺寸,以使纵横比保持恒定。

看到笔图像缩放基本由无肢贝拉米-罗伊兹( @AmeliaBR上) CodePen

相反,SVG图像可以以任何像素大小绘制,因此它们不需要明确定义的高度或宽度。 而且它们并不总是具有明确定义的宽高比。 如果希望SVG缩放以适合您提供的尺寸,则需要显式提供此信息(以及更多信息)。

如果您不这样做,SVG将根本无法扩展。 下面的示例使用嵌入式SVG,在不更改绘制图形大小的情况下,调整元素的尺寸(虚线):

见笔无标SVG被阿梅利亚贝拉米-罗伊兹( @AmeliaBR上) CodePen

为什么会这样呢? 因为SVG并非(仅仅是)图像。 SVG是一个文档。 尽管上面的示例使用了嵌入式SVG,但使用<object><iframe>也很容易。 即使您使用<img>标签嵌入相同的SVG代码,其外观也将完全相同。

当包含带有<iframe>HTML文件时,您不希望在更改框架大小时缩放其中的文本。 与SVG相同。 默认情况下,无论画布大小如何,都将以代码中指定的尺寸绘制它。如果将这些SVG的高度或宽度(或两者)设置为auto ,会发生什么? 将使用HTML替换元素的默认大小:宽300px,高150px。 这适用于<img><object><iframe> 。 默认的300×150尺寸也适用于HTML文档中的内联<svg>元素,但这是HTML5规范中的一个相对较新的共识:默认情况下,其他浏览器会将内联SVG扩展为视口的完整大小,相当于width: 100vw; height: 100vh; width: 100vw; height: 100vh; —这是直接在自己的浏览器标签中打开的SVG文件的默认大小。 Internet Explorer通过使用100%的宽度和150px的高度(用于图像和嵌入式SVG)来缩小差异。

换句话说,即使您认为300×150是理想的图像尺寸(尽管为什么会这样?),也不要依赖于HTML中<svg>的默认尺寸。

除了确定SVG的大小,还必须确定希望图形缩放以适合该大小的方式。 下面,我描述了在最常见的情况下获取所需比例尺所需的代码:

  • 缩放以适合特定大小,而不会扭曲图像
  • 缩放以适合特定大小,并根据需要拉伸或压缩图形
  • 缩放以适合可用宽度,同时保持宽高比
  • 以非均匀的方式缩放,以使图形的某些部分缩放比例与其他部分不同

但首先:如果您想控制SVG的缩放比例,则需要熟悉SVG缩放比例属性和其他可用工具。

SVG缩放工具箱

其他图像可以缩放,因为浏览器知道图像的高度,宽度和纵横比,并且可以一起调整所有内容。 为SVG提供这​​些属性是按比例缩放的第一步。 但是,缩放SVG超出了其他图像可能实现的范围。

heightwidth属性

乍一看SVG规范将建议顶级svg元素上的heightwidth属性将隐式设置长宽比,从而使SVG像其他图像一样缩放。 的确,当您将SVG用作图像时,设置高度和宽度会覆盖默认尺寸。 但是,这并非易事:

  • 如果使用<img>嵌入SVG,则在大多数浏览器中(如果不是Internet Explorer),设置heightwidth将使SVG缩放可预测。 使用CSS,例如img { width: 100%; height: auto; } img { width: 100%; height: auto; } img { width: 100%; height: auto; } ,IE将自动缩放图像区域以保持width:height纵横比恒定,但不会缩放实际图形以匹配图像尺寸的比例。
  • 如果您使用<object><embed><iframe>嵌入SVG,则在<svg>上设置高度和宽度不会更改框架的大小; <svg> 。 如果SVG太大,您只会在iframe中获得滚动条。
  • 如果您使用内联SVG(即<svg>直接在您HTML5代码),那么<svg>元素具有双重用途,在网页内以及在SVG中定义的图像区域。 您使用CSS为SVG设置的任何高度或宽度都将覆盖<svg>上的height和width属性。 像svg {width: 100%; height: auto;} svg {width: 100%; height: auto;}将取消您在代码中设置的尺寸和宽高比,并为您提供嵌入式SVG的默认高度。 如上所述,根据浏览器的不同,该分辨率将为150px或100vh。

因此,请忘记heightwidth 。 您实际上并不想设置确切的高度和宽度,而是希望SVG缩放以匹配您在CSS中设置的宽度和/或高度。 您想要的是为图像设置长宽比 ,并使绘图比例适合。 您需要一个viewBox

viewbox属性

SVG viewBox在一个小属性中viewBox了很多魔力。 这是使矢量图形可缩放矢量图形的最后一部分。 viewBox做很多事情:

  • 它定义图像的纵横比。
  • 它定义了如何缩放SVG内部使用的所有长度和坐标以适合可用的总空间。
  • 它定义了SVG坐标系的原点,即x = 0和y = 0的点。

viewBox<svg>元素的属性。 它的值是四个数字的列表,用空格或逗号分隔:x,y,宽度,高度。 宽度是SVG代码中以用户坐标/ px为单位的宽度,应缩放以填充绘制SVG的区域的宽度(SVG语言中的视 )。 同样,高度是应该缩放以填充可用高度的px /坐标数。 即使您的SVG代码使用其他单位,例如英寸或厘米,它们也将被缩放以匹配viewBox创建的整体比例。

x和y数字指定比例缩放的viewBox坐标系中的坐标,该坐标用于SVG视口的左上角。 (坐标从左到右和从上到下增加,与在JavaScript中标识页面位置相同)。 为了进行简单缩放,可以将两个值都设置为0。但是,x和y值有两个用途:创建一个以图形为中心的原点的坐标系(这可以使定义和变换形状更加容易),或者裁剪比原始定义更紧的图像。

一些示例viewBox值:

  • viewBox="0 0 100 100" :定义一个坐标系,其宽度为100个单位,高度为100个单位。 换句话说,如果SVG包含一个以图形为中心且半径为50px的圆,则即使该图片以全屏显示,它也会填满SVG图像的高度或宽度。 如果您的SVG包含一个height="1in"的矩形,它也会几乎填满整个屏幕,因为CSS中1英寸= 96像素,所有长度都将按比例缩放。
  • viewBox="5 0 90 100" :几乎相同的视图,但在左右两侧裁剪了5%,因此总宽度= 90个单位,而x坐标在左侧= 5。
  • viewBox="-50 -50 100 100" :具有相同比例的视图,但现在左上角已指定坐标(-50,-50)。 这意味着右下角的坐标为(+50 +50)。 在(100,100)处绘制的任何形状都将远离屏幕。 如果要绘制一个完全填满图像区域的圆,则该圆将以(0,0)为中心。

viewBox添加到<svg> (默认情况下,Inkscape和Illustrator之类的编辑器会添加它)后,您可以将该SVG文件用作图像或内联SVG代码,并且可以完美缩放以适合任何大小你给它。 但是,它仍然无法像其他任何图像一样缩放。 默认情况下,如果您提供的尺寸与宽高比不匹配, 不会拉伸或变形 。 相反,将调整比例,以保留代码中定义的宽高比。

preserveAspectRatio属性

viewBox属性具有一个补充, preserveAspectRatio 。 除非存在用于定义图像纵横比的viewBox否则它无效。 当有viewBox时, preserveAspectRatio描述了如果viewBox的纵横比与视口的纵横比不匹配时如何缩放图像。 在大多数情况下,默认行为效果很好:将图像缩放到恰好适合高度和宽度,并且将其居中放置在任何额外空间内。

就像viewBox一样, preserveAspectRatio在单个属性中具有大量信息。 可以使用preserveAspectRatio="xMidYMid meet"显式设置默认行为。 第一部分, xMidYMid告诉浏览器在x和y方向xMidYMid缩放后的viewBox区域居于可用视口区域的中心。 您可以替换MidMinMax对齐图形平齐一方或另一方。 但是,请注意驼峰大写:SVG是XML,因此区分大小写。 x是小写字母,而Y是大写字母。

默认preserveAspectRatio后半部分, meet ,是告诉浏览器缩放图形直到恰好适合高度和宽度的部分。 CSS背景图片的等效background-size: contain;background-size: contain; 。 SVG的替代值是slice (相当于background-size: cover; )。 slice值将缩放图像以适合更大的尺寸,并切掉多余的部分。 除此以外,它并不一定要削减掉多余的部分。 这取决于overflow属性的值。

(旁注:如果希望每个图像都可以在其给定的尺寸上居中,而不是被拉伸或变形, 则新的object-fit CSS属性可让您对其他图像类型执行相同操作 。)

preserveAspectRatio="none"选项,以使SVG完全像光栅图像一样缩放(但分辨率要好得多),拉伸或压缩以适合您提供的高度和宽度。

如何缩放SVG以适合特定大小(不使图像失真)

可能最常见的要求是使SVG图标比例尺适合特定的大小,而不会失真。 尽管您可以使用preserveAspectRatio来调整对齐方式,但是viewBox属性实际上是您所需要的。

如前所述,如果要在图形编辑器中创建SVG,则它可能已经包含了viewBox。 但是,您可能需要调整viewBox以使定位恰到好处。 在其余的示例中,已为该金罐图形提供了viewBox="0 0 60 55" 。 在它周围留出一些额外的空间; 要创建一个裁剪图标,可以使用viewBox="4.5 1.5 51 49" 。 以下示例还显示了默认的preserveAspectRatio的效果,该效果将图形居中放置在所提供的空间中:

参见Pen Normal SVG缩放,并在 CodePen上使用Amelia Bellamy-Royds( @AmeliaBR )的viewBox

如何缩放SVG以适合可用宽度(并调整高度以匹配)

带有viewBox SVG可以缩放以适合您提供的高度和宽度。 但是自动调整大小呢? 对于光栅图像,您可以设置width height ,并使另一个比例匹配。 SVG可以做到吗?

可以,但是变得复杂。 有两种不同的方法可供选择,具体取决于您包含SVG的方式。

选项1:使用图片自动调整大小

当SVG文件具有viewBox并将其嵌入<img> ,浏览器将(几乎总是)缩放图像以匹配viewBox定义的宽高比。

CodePen查看 Amelia Bellamy-Royds( @AmeliaBR )的Pen Auto-Scaling SVG图像

但是,Internet Explorer仍然是SVG的祸根。 尽管通常正常工作,但我使用display: table-cell在本示例的早期版本中布置了数字,并且IE以怪异的方式扭曲了图像。

如果完全自动调整图像大小,则Internet Explorer将应用标准的默认300×150大小。 但是,其他浏览器将应用{ width: 100%; height: auto; } { width: 100%; height: auto; } { width: 100%; height: auto; }默认如果图像具有viewBox ; 此行为未在任何规范中定义。

回顾一下:要自动缩放用作<img> SVG,

  1. 设置一个viewBox属性。
  2. 设定为高度或宽度的至少一个
  3. 如果您想支持Internet Explorer,请不要将其放在表格布局中。
选项2:使用CSS背景图片和padding-bottom Hack

在大多数情况下,将SVG用作CSS背景图片的方式与<img>使用SVG的方式几乎相同(但还有一个额外的好处,即可以为旧版浏览器定义栅格后备)。 较旧的浏览器在将图像转换为光栅后而不是之前(即像素化)缩放图像时,存在一些错误,但是在大多数情况下, viewBox就是您所需要的。

但是,自动调整大小不是CSS背景图片的选项; 毕竟,该图像应该位于元素HTML内容之后。 如果您希望元素与要使用的图像的长宽比完全匹配,则将不得不对其进行一些修改。

有一定数量CSS属性,可让您根据可用宽度调整基于高度的属性。 如果将block-layout元素的borderpaddingmargin设置为百分比值,则即使相对于顶部底部边框,padding和margin,百分比也将相对于容器的可用宽度进行计算。

预期的目的是即使高度是自动的,也要创建均匀大小的边框和填充。 但这不是重点。 出于我们的目的,关键是您可以与宽度成比例地调整元素的总高度。 换句话说,您可以控制纵横比。 要创建宽度为100%的<div> ,该宽度与您用作背景的图像的4:3长宽比完全匹配,可以使用:

.ratio4-3 {
 width: 100%;
 background-image: url(image-with-4-3-aspect-ratio.svg);
 background-size: cover;
 height: 0;
 padding: 0; /* reset */
 padding-bottom: calc(100% * 3 / 4);
}

注意事项:

  • 要获得所需高度(以可用宽度的百分比表示),请将宽度百分比乘以所需高度系数,再除以所需宽度系数。
  • 如果要支持不支持calc()浏览器,则需要自己(或使用CSS预处理器)进行数学calc()
  • 如果默认情况下将每个元素设置为box-sizing: border-box ,则必须将其重新设置为使用box-sizing: content-box 。 我们希望它是height: 0毕竟是height: 0 填充。
  • 由于IE5中的问题,使用padding-bottom属性代替了padding-top属性。 尽管您可能并不担心支持IE5,但您还是应该保持一致。 毕竟,这被称为padding-bottom hack。

对于黄金罐图像,长宽比为60:55,底部填充为92%。 实际上,它看起来像这样:

请参见CodePen上的Ascalia Bellamy-Royds( @AmeliaBR )将Pen 缩放<div>以匹配图像长宽比

选项3:使用嵌入式SVG和最新的Blink / Firefox浏览器

SVG图像很好,但是在许多情况下,您会更喜欢使用嵌入式SVG。 内联SVG减少了HTTP请求的数量,允许用户交互,并且可以通过您的主网页中CSS进行修改。 但是会扩展吗?

如果您使用的是最新的Firefox或Blink浏览器,它将使用。 只需在<svg>上设置viewBox ,然后将height或width之一设置为auto 。 浏览器将对其进行调整,以使总纵横比与viewBox相匹配。 美丽。

见笔自动缩放SVG内联通过阿米莉亚·贝拉米-罗伊兹( @AmeliaBR上) CodePen

但是有可能,这些并不是您需要支持的唯一浏览器。

许多浏览器(2014年夏季之前发布的IE,Safari和Opera和Chrome版本)将不会自动调整内置SVG的大小。 如果您未同时指定高度和宽度,则这些浏览器将应用其通常的默认大小,如前所述,不同的浏览器会有所不同。 图像将缩放以适合该高度或宽度,再次在其周围保留额外的空白。 同样,如果同时保留height width auto ,也会发生不一致的情况。

解决方案是再次使用padding-bottom hack自己控制宽高比。 适用于内联SVG以及<object><iframe>和其他替换元素(如<video>的最简单方法是使用容器元素。

选项4:在容器上使用padding-bottom Hack

要使用容器<div> ,请向<div>添加类或内联样式以为其提供正确的宽高比,就像上面使用背景图像时所做的那样。 还要设置position: relative对于容器,以便它将成为绝对定位的内容的参考框架。 然后将SVG(或其他对象)设置为position: absolute ,高度和宽度为100%。 需要绝对定位,以便相对于<div>的高度( 包括填充)而不是相对于零高度内容区域来计算百分比。

除非您有很多具有相同长宽比的图形,否则通常最好声明内嵌padding-bottom ,以使它就在需要匹配的viewBox旁边:

<div class="scaling-svg-container" 
   style="padding-bottom: 92% /* 100% * 55/60 */">
  <svg class="scaling-svg" viewBox="0 0 60 55" >
    <!-- SVG content -->
  </svg>
</div>
.scaling-svg-container {
 position: relative; 
 height: 0; 
 width: 100%; 
 padding: 0;
 padding-bottom: 100%; 
 /* override this inline for aspect ratio other than square */
}
.scaling-svg {
 position: absolute; 
 height: 100%; 
 width: 100%; 
 left: 0; 
 top: 0;
}

见笔缩放联SVG使用软垫集装箱被阿梅利亚贝拉米-罗伊兹( @AmeliaBR上) CodePen

容器方法可行,但要付出标记中额外包装元素的代价。 而且,它也不是通用容器:它必须根据您的SVG所需的确切长宽比进行自定义。 如果您不希望将其扩展到完整的100%,事情会变得更加棘手。 您将需要使用另一个包装器<div>设置所需的宽度和其他定位属性。 我个人更希望将有关SVG宽高比的所有信息保留在SVG代码本身中。 为此,对于内联SVG,您需要告诉浏览器画出轮廓线并进入填充。

选项5:在Inline <svg>元素上使用padding-bottom Hack

若要使用padding-bottom hack控制整个<svg>区域的长宽比,则官方高度将(基本上)为零。 使用默认的preserveAspectRatio值,图形将按比例缩小到无。 相反,您希望图形可以拉伸以覆盖您提供的整个宽度,并溢出到您精心设置为正确的宽高比的填充区域上。

再次,我喜欢对padding-bottom宽高比使用内联样式,因为需要针对viewBox属性对其进行自定义。 在下面的示例中,我也将其用于其他样式属性,尽管如果您有许多需要相同效果的图形,则可以使用一个类:

<svg viewBox="0 0 60 55" preserveAspectRatio="xMidYMin slice"
   style="width: 100%; padding-bottom: 92%; height: 1px; overflow: visible">
  <!-- SVG content -->
</svg>

那里还有其他一些细节:

  • 高度为1px,而不是0,否则SVG可能根本无法绘制(Firefox)或根本无法缩放(Chrome)。
  • 所述preserveAspectRatio使用YMin为垂直取向,从而使所述图形抵靠的顶整齐地对准<svg>内容区域中,溢出进入底部填充。
  • 尽管“ overflow: visible可能是HTML的默认设置,但需要为SVG显式设置。

如果您希望SVG缩放到小于100%宽度的某个百分比,请记住相应地调整padding-bottom 。 或使用包装器<div>设置大小。

见笔缩放SVG内联使用填充和切片的阿米莉亚·贝拉米-罗伊兹( @AmeliaBR上) CodePen

如何缩放,拉伸和压缩SVG以完全适合特定大小

尽管通常希望保持宽高比,但有时图像是要拉伸以适合的抽象图像或灵活图像。

选项1:使用百分比

拉伸以适合的一种选择是对SVG中的所有大小和位置属性使用百分比值。

见笔Flex的缩放SVG使用百分比由阿梅利亚贝拉米-罗伊兹( @AmeliaBR上) CodePen

关于百分比和SVG的注意事项:

  • 如果您使用百分比来拉伸和压缩,请不要包含viewBox (尽管您可以指定默认的高度和宽度)。
  • SVG中的某些长度与高度或宽度都没有明确关联; 例如,圆的半径。 如果在这些情况下使用百分比值,则长度将被计算为等效的高度和宽度百分比的几何平均值(平方和的平方根除以2的平方根)。 这保留了对角线与矩形线的勾股定理关系,但在其他方面有些混乱。
  • SVG中的许多长度不能用百分比指定,最重要的是<path><polygon>元素的坐标。
选项2:使用preserveAspectRatio="none"

如果您想灵活地缩放还包括SVG路径的SVG,则需要使用viewBox加上viewBox preserveAspectRatio="none" 。 这是那条彩虹的稍加幻想的版本,有浮云 s:

请参阅CodePen上的Amelia Bellamy-Royds( @AmeliaBR )的使用prepareAspectRatio =“ none”的Pen Flex-Scaling SVG

请注意,使用preserveAspectRatio="none" ,所有内容均会被均匀拉伸或压缩,就像您缩放其他图像类型的比例不均一样。 这意味着圆圈会变成椭圆形,并且文字也会变形。 为避免这种情况,您需要使用多种缩放方法。

如何分别缩放SVG的各个部分

viewBoxpreserveAspectRatio属性非常灵活。 一旦你停止SVG的思维只是另一种图像格式,你就可以开始问自己, 希望你的图形,以规模作为窗口改变大小。

要意识到的重要一点是,您不需要为整个SVG定义单个viewBoxpreserveAspectRatio选项。 相反,您可以使用嵌套的<svg>元素,每个元素都有自己的缩放属性,以独立地具有图形缩放的不同部分。 (您也可以在<symbol><pattern>元素上使用这些属性,并且可以在SVG中嵌入的其他图像上使用preserveAspectRatio 。)通过这种方法,您可以创建标题图,该图可以拉伸以填充宽屏显示而无需占用以及过高的高度:

见笔Flex的缩放SVG使用嵌套SVGs被阿梅利亚贝拉米-罗伊兹( @AmeliaBR上) CodePen

翻译自: https://css-tricks.com/scale-svg/

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值