图案
<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属性将被忽略。