SVG入门-纹理

247 阅读2分钟

图案


<patterns>的功能非常强大,在pattern元素内部你可以包含任何之前包含过的其它基本形状,并且每个形状都可以使用之前学习过的任何样式样式化,包括渐变和半透明。用<pattern>定义的图案,可以被用在其他元素的fill或者stroke属性中。

<pattern id="pa">
    <!-- 描绘pattern图案的svg元素 -->
</pattern>
<rect x="0" y="0" height="100" width="100" style="fill:url(#pa); stroke:url(#pa)">

图案的填充方式 patternUnits

pattern有两种填充方式:objectBoundingBox和userSpaceOnUse:

objectBoundingBox为patternUnits的默认属性值。可以理解为在指定区域内,规定沿x轴和y轴平铺指定数量的图案。我们通过指定width和height来间接规定图案平铺的数量。因为这时,width和height被限制在0-1,或者0%-100%之间,即宽度或高度占填充区域高度或宽度的百分比。可想而知20%放5个,40%放2.5个。

<svg width="500" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
  	<defs>
    	<pattern id="tile" width="0.2" height="0.2" patternUnits="objectBoundingBox">
        	<path d="M 0 0 Q 5 20 10 10 T 20 20" stroke="black" fill="none"></path>
        	<rect x="0" y="0" width="20" height="20" stroke="grey" fill="none"></rect>
    	</pattern>
	</defs>
	<rect x="20" y="20" width="100" height="100" fill="url(#tile)" stroke="grey">	</rect>
	<rect x="140" y="20" width="70" height="80" fill="url(#tile)" stroke="grey"></rect>
	<rect x="230" y="20" width="150" height="180" fill="url(#tile)" stroke="grey"></rect>
</svg>

在这里插入图片描述

userSpaceOnUse是将pattern的宽度和高度固定住,在指定区域内平铺,能铺多少铺多少,超出部分裁掉。相应的width和height即pattern的宽度和高度。

<svg width="500" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <pattern id="tile2" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
            <path d="M 0 0 Q 5 20 10 10 T 20 20" stroke="grey" fill="none"></path>
            <rect x="0" y="0" width="20" height="20" stroke="grey" fill="none"></rect>
        </pattern>
    </defs>
    <rect x="0" y="0" width="100" height="100" fill="url(#tile2)" stroke="black"></rect>
    <rect x="100" y="0" width="70" height="80" fill="url(#tile2)" stroke="black"></rect>
    <rect x="170" y="0" width="150" height="130" fill="url(#tile2)" stroke="black"></rect>
</svg>

在这里插入图片描述

需要注意的是,userSpaceOnUse的pattern并不会在每个指定区域内重新以区域左上角开始排序。userSpaceOnUse的pattern的起点坐标只有一个,就是其x和y表示的在svg画布坐标系中的位置。 所以可以看到第二和第三个图相邻的两个图,贝塞尔曲线是连续的。我们可以改变pattern的x和y看下结果。

<svg width="500" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <defs>
    <pattern id="tile2" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
        <path d="M 0 0 Q 5 20 10 10 T 20 20" stroke="grey" fill="none"></path>
        <rect x="0" y="0" width="20" height="20" stroke="grey" fill="none"></rect>
    </pattern>
    </defs>
    <rect x="10" y="10" width="100" height="100" fill="url(#tile2)" stroke="black"></rect>
    <rect x="110" y="20" width="70" height="80" fill="url(#tile2)" stroke="black"></rect>
    <rect x="180" y="30" width="150" height="130" fill="url(#tile2)" stroke="black"></rect>
</svg>

在这里插入图片描述

图案内部缩放 patternContentUnits

patternContentUnits也有两个属性:objectBoundingBox和userSpaceOnUse(默认属性值)

在userSpaceOnUse模式下,pattern内部元素的大小不会因为pattern的缩放而改变。userSpaceOnUse是patternContentUnits的默认属性值。

在objectBoundingBox模式下,pattern内部元素所有属性的数值都会根据设置的比例,乘以pattern的width或height计算出实际长度。pattern内部元素所有属性的数值如果后面不带百分号%,都乘上100作为百分比数。所以像stroke-width默认值是1的这种属性,如果不指定一个数值,就会被当成100%来计算,结果就是撑满整个pattern。

<svg width="500" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <pattern id="tile1" patternUnits="objectBoundingBox"  x="0" y="0" width=".2" height=".2" patternContentUnits="objectBoundingBox">
            <path d="M 0 0 Q .05 .2 .1 .1 T .2 .2" style="stroke: black; fill: none; stroke-width: .01;"></path>
            <path d="M 0 0 h .2 v .2 h-.2z" style="stroke: black; fill: none; stroke-width: .01;"></path>
        </pattern>
    </defs>
    <g transform="translate(20,20)">
        <rect x="0" y="0" width="100" height="100" style="fill: url(#tile1  ); stroke: black;"></rect>
    </g>
    <g transform="translate(135,20)">
        <rect x="0" y="0" width="70" height="80" style="fill: url(#tile1); stroke: black;"></rect>
    </g>
    <g transform="translate(220,20)">
        <rect x="0" y="0" width="150" height="80" style="fill: url(#tile1); stroke: black;"></rect>
    </g>
</svg>

在这里插入图片描述

用viewBox代替patternContentUnits

上例用viewBox的实现如下:

<pattern id="tile2" patternUnits="objectBoundingBox"  x="0" y="0" width=".2" height=".2" viewBox="0 0 20 20" preserveAspectRatio="none">
    <path d="M 0 0 Q 5 20 10 10 T 20 20" style="stroke: black; fill: none; stroke-width: 1;"></path>
    <path d="M 0 0 h 20 v 20 h-20z" style="stroke: black; fill: none; stroke-width: 1;"></path>
</pattern>

当然,通过设置不同的preserveAspectRatio还可以实现一些patternContentUnits="objectBoundingBox"无法实现的功能。如果有viewBox属性,patternContentUnits属性将被忽略。