裁剪以适合svg图案

时间:2014-04-05 17:06:10

标签: svg image-scaling

我有模式,每个模式都有一个图像。我需要将图像缩放到容器的整个宽度或高度,这些容器是路径,同时保留它们的比例。从本质上讲,如果设置min-width:100%; min-height:100%;

,它们可能需要像html图像一样

我之前没有使用过很多svgs,也不知道要改变哪些属性来获得这种行为。我一直在尝试各种viewBoxpreserveAspectRatiopatternUnits等组合,但我似乎无法得到我想要的东西。

1 个答案:

答案 0 :(得分:58)

要实现这一点,您需要了解objectBoundingBox单位在SVG中的工作方式,以及preserveAspectRatio的工作原理。

Object Bounding Box Units

渐变,图案和许多其他SVG要素的大小和内容可以根据对象的大小(pathrectcircle)来指定通过指定objectBoundingBox作为单位进行绘制。相反的是userSpaceOnUse,它使用绘制形状的坐标系。

对象边界框单位通常是声明图形填充元素的 size position 的默认值;您可以通过在patternUnits元素上设置<pattern>属性来更改此设置。但是,用户空间单位通常是内容图形中使用的任何单位的默认值;要更改此设置,请设置patternContentUnits属性。

所以第一步:要创建完全填充形状的图案,您需要:

  • 将图案的高度和宽度声明为100%(或1);默认情况下,这些将相对于边界框进行解释。)
  • 声明patternContentUnits="objectBoundingBox"
  • 调整内容(图片)的大小,使其高度和宽度为1.

不能使用100%作为模式内容本身内1个对象边界框单元的同义词(即图像尺寸);百分比是相对于 SVG 大小而不是objectBoundingBox解释的。*

我应该提一下,因为你说你的形状是<path>元素,所以对象边界框是垂直于绘制路径的坐标系的最小矩形,包含所有路径&#39 s点。它不包括中风。例如,水平直线具有零高度边界框;有角度的线具有边界框矩形,使得该线是框的对角线。 如果您的路径形状笨拙和/或与坐标系不完全对齐,则边界框可能比路径大得多。

Preserving Aspect Ratio

preserveAspectRatio属性适用于图片和可以具有viewBox属性的任何元素:父<svg>,嵌套<svg><symbol>,{ {1}}和<marker>。对于图像,纵横比是根据图像的固有宽度:高度比计算的,对于所有其他图像,它是根据viewBox attribute中的宽度:高度数计算的。

对于任一类型的元素,如果声明的元素的高度或宽度与宽高比不匹配,则<pattern>属性将确定是否将内容拉伸以适合({{1 }}),大小适合一个维度并在另一个维度中裁剪(preserveAspectRatio)或缩小以适应具有额外空间的两个维度(none);对于slicemeet选项,您还可以指定如何对齐空间中的内容。

但是,重要的是要注意可用空间的宽高比是在当前坐标系中计算的,而不是以屏幕像素计算。因此,如果更高级别的viewBox或转换改变了宽高比,即使在当前元素上设置了preserveAspectRatio属性,事情仍然可能会失真。

另一件要知道的是默认值通常是不是 meet。对于slicenone元素,默认值为<image> - 即缩小到适合和居中。当然,如果模式元素具有<pattern>属性,则此默认值仅对模式元素产生影响(否则,假设它没有保留宽高比)。

您想要用于xMidYMid meet的价值取决于图片和设计:

  • 图像是否应拉伸以适合viewBox形状?
  • 是否应保持图像宽高比,但尺寸要完全适合或覆盖形状?

在第一种情况下(拉伸),你不需要对preserveAspectRatio元素做任何事情(没有viewBox意味着没有宽高比控制),但你需要专门关闭图像的宽高比控制。

相反,如果你想避免图像失真,你需要:

  • preserveAspectRatio="none"元素上设置<pattern> viewBox属性;
  • 如果您想要与默认值不同的内容,请在preserveAspectRatio上设置<pattern>属性。

工作示例

This fiddle shows three ways of getting a pattern image to fill a shape

  • 第一行关闭了方面控制。

    preserveAspectRatio
  • 中间行对<image>元素进行宽高比控制,因此裁剪图片以适合图案,但是当在矩形中绘制图案时图片仍然会失真,因为{{1定义坐标系的单位对于高度与宽度不同。 (圆圈中的图像不会扭曲,因为圆的边界框是正方形。)

    <!-- pattern1 - no aspect ratio control -->
    <pattern id="pattern1" height="100%" width="100%"
             patternContentUnits="objectBoundingBox">
        <image height="1" width="1" preserveAspectRatio="none" 
               xlink:href="/*url*/" />
    </pattern>
    
  • 底行在图像图案上设置了<image>(并且在图案上设置了objectBoundingBox)。图像被裁剪但未拉伸。

    <!-- pattern2 - aspect ratio control on the image only -->
    <pattern id="pattern2" height="100%" width="100%"
             patternContentUnits="objectBoundingBox">
        <image height="1" width="1" preserveAspectRatio="xMidYMid slice" 
               xlink:href="/*url*/" />
    </pattern>
    

Output from the JS fiddle example, showing the images described

来源图片by Stefan Krause, from Wikimedia Commons。原始宽高比为4:6纵向模式。

* 2015-04-03更正