要使其工作,您需要了解 objectBoundingBox 单位在 SVG 中的工作原理,以及 preserveAspectRatio 的工作原理。
可以根据正在绘制的对象(path、rect、circle)的大小来指定渐变、图案和许多其他 SVG 功能的大小和内容,通过指定 @987654332 来绘制@ 为单位。相反的总是userSpaceOnUse,它使用绘制形状的坐标系。
对象边界框单位通常是声明图形填充元素的size和position的默认值;您可以通过在<pattern> 元素上设置patternUnits 属性来更改此设置。但是,用户空间单位通常是内容图形中使用的任何单位的默认值;要更改此设置,请设置 patternContentUnits 属性。
所以第一步:要创建一个完全填充形状的图案,您需要:
- 将图案的高度和宽度声明为100%(或1);默认情况下,这些将相对于边界框进行解释)。
- 声明
patternContentUnits="objectBoundingBox"。
- 调整内容(您的图片)的大小,使其高度和宽度均为 1。
您不能在图案内容本身(即图像尺寸)中使用 100% 作为 1 个对象边界框单元的同义词;百分比是相对于 SVG 大小解释的,而不是 objectBoundingBox.*
我应该提到,因为您说您的形状是<path> 元素,所以对象边界框是垂直于绘制路径的坐标系并包含所有路径点的最小矩形。它不包括中风。例如,一条水平直线有一个高度为零的边界框;有角度的线有一个边界框矩形,使得该线是框的对角线。 如果您的路径形状不规则和/或与坐标系不太对齐,则边界框可能比路径大得多。
preserveAspectRatio 属性适用于图像和任何可以具有viewBox 属性的元素:父<svg>、嵌套<svg>、<symbol>、<marker> 和<pattern>。对于图像,纵横比是根据图像的固有宽高比计算得出的,对于所有其他图像,纵横比是根据viewBox attribute 中的宽高比计算得出的。
对于任一类型的元素,如果您声明的元素的高度或宽度与纵横比不匹配,preserveAspectRatio 属性将确定内容是否将被拉伸以适应 (none),大小为适合一个维度并在另一个维度中裁剪 (slice) 或缩小以适应两个维度并留出额外空间 (meet);对于meet 和slice 选项,您还可以指定如何对齐空间中的内容。
但是,重要的是要注意可用空间的纵横比是在当前坐标系中计算的,而不是在屏幕像素中。因此,如果更高级别的 viewBox 或转换改变了纵横比,即使在当前元素上设置了 preserveAspectRatio 属性,事情仍然会发生扭曲。
要知道的另一件事是 default 值通常是 not none。对于<image> 和<pattern> 元素,默认值为xMidYMid meet - 即缩小以适合和居中。当然,此默认设置仅在模式元素具有viewBox 属性时才对模式元素产生影响(否则,假定它没有要保留的纵横比)。
您想为preserveAspectRatio 使用什么值取决于图像和设计:
- 是否应该拉伸图像以适应形状
preserveAspectRatio="none"?
- 是否应保持图像纵横比,但调整大小以完全适合或覆盖形状?
在第一种情况下(拉伸),你不需要对<pattern>元素做任何事情(没有viewBox意味着没有纵横比控制),但是你做需要专门关闭图像的纵横比控制。
相比之下,如果您想避免图像失真,您需要:
- 在
<pattern> 元素上设置viewBox 和 preserveAspectRatio 属性;
- 如果您想要不同于默认值的内容,请在
<image> 上设置 preserveAspectRatio 属性。
工作示例
This fiddle shows three ways of getting a pattern image to fill a shape.
-
顶行关闭了纵横比控制。
<!-- 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>
-
底行在图像和图案上都设置了preserveAspectRatio(在图案上还设置了viewBox)。图像被裁剪但未被拉伸。
<!-- pattern3 - aspect ratio control on both image and pattern -->
<pattern id="pattern3" height="100%" width="100%"
patternContentUnits="objectBoundingBox"
viewBox="0 0 1 1" preserveAspectRatio="xMidYMid slice">
<image height="1" width="1" preserveAspectRatio="xMidYMid slice"
xlink:href="/*url*/" />
</pattern>
源图片by Stefan Krause, from Wikimedia Commons。原来的纵横比是 4:6 纵向模式。
* 2015-04-03 更正