裁剪以适合svg图案

rap*_*ltm 22 svg image-scaling

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

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

Ame*_*aBR 62

要使其工作,您需要了解objectBoundingBox单位在SVG中的工作方式以及preserveAspectRatio工作原理.

对象边界框单位

的大小和渐变,图案的内容和许多其它特征SVG可以在对象的大小来规定(path,rect,circle),其被通过指定绘objectBoundingBox作为单位.总是相反userSpaceOnUse,它使用绘制形状的坐标系.

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

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

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

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

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

保持纵横比

preserveAspectRatio属性适用于图像,并且,可以有一个的任何元素viewBox属性:父<svg>嵌套<svg>,<symbol>,<marker><pattern>.对于图像,纵横比是根据图像的固有宽度:高度比计算的,对于所有其他图像,它是根据viewBox属性中的width:height数计算的.

对于任一类型的元素,如果声明元素的高度或宽度与宽高比不匹配,则preserveAspectRatio属性将确定是否将内容拉伸到fit(none),大小适合一个维度并在另一个维度中裁剪(slice)或缩小以适应两个尺寸的额外空间(meet); for meetsliceoptions您还可以指定如何对齐空间中的内容.

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

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

您想要使用的价值preserveAspectRatio取决于图像和设计:

  • 图像应该拉伸以适应形状preserveAspectRatio="none"吗?
  • 是否应保持图像纵横比,但尺寸完全适合或覆盖形状?

在第一种情况(拉伸),则不需要做任何事来的<pattern>元件(没有视框意味着没有宽高比控制),但你需要专门关闭纵横比控制在图像上.

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

  • 元素的集合viewBox preserveAspectRatio属性<pattern>;
  • 如果您想要不同于默认值preserveAspectRatio的内容<image>,请设置属性.

工作实例

这个小提琴显示了三种获取图案图像以填充形状的方法.

  • 顶行已禁用方面控制.

    <!-- 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>
    
    Run Code Online (Sandbox Code Playgroud)
  • 中间行对<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>
    
    Run Code Online (Sandbox Code Playgroud)
  • 底行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>
    
    Run Code Online (Sandbox Code Playgroud)

来自JS小提琴示例的输出,显示所描述的图像

来自维基共享资源的Stefan Krause的来源图片.原始宽高比为4:6纵向模式.

*2015-04-03更正

  • 感谢精彩详细的回复!我认为我缺少的主要内容是如何使用 `preserveAspectRatio`,但我从中学到了很多。 (3认同)
  • 很高兴你弄清楚了。我决定这是一个足够复杂的话题,值得进行从头到脚的讨论,以便将来可以帮助其他人,而不是花一打来回的评论试图找出哪个拼图让你绊倒向上。 (2认同)
  • @Alexandr_TT 链接已修复。如果你以后遇到任何其他人,你需要用 `https://jsfiddle.net/` 替换 `http://fiddle.jshell.net`。 (2认同)