8.1 Patterns
To use a pattern, you define a graphic object that is replicated horizontally and vertically to fill another object (or stroke). This graphic object is called a tile, because the act of filling an object with a pattern is very much like covering an area of a floor with tile.
Example of a tile
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<!-- quadratic curves smoothly connected -->
<path d="M 0 0 Q 5 20 10 10 T 20 20"
style="fill:none; stroke:black;"/>
<!-- square frame -->
<path d=" M 0 0 h 20 v 20 h -10 Z" style="
fill:none; stroke:gray;"/>
</svg>7.1.1 Pattern and PatternUnits
To create a pattern tile, you must enclose the path elements that describe your tile in a
pattern element, and then make several decisions. The first decision is how you wish
to space the tiles, and this is reflected in the patternUnits attribute, which can be
patternUnits="objectBoundingBox" or patternUnits="userSpaceOnUse".
Example 1. A pattern with width="20%" height="20%" and with default patternUnits="objectBoundingBox"
<svg width="200" height="400" viewBox="0 0 200 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="tile" x="0" y="0" width="20%" height="20%" patternUnits="objectBoundingBox">
<!-- quadratic curves smoothly connected -->
<path d="M 0 0 Q 5 20 10 10 T 20 20"
style="fill:none; stroke:black;"/>
<!-- square frame -->
<path d=" M 0 0 h 20 v 20 h -20 z" style="
fill:none; stroke:gray;"/>
</pattern>
</defs>
<rect x="20" y="20" width="100" height="100" style="fill:url(#tile); stroke:black"/>
<rect x="20" y="130" width="70" height="80" style="fill: url(#tile); stroke: black;"/>
<rect x="20" y="220" width="150" height="130" style="fill: url(#tile); stroke: black;"/>
</svg>Example 2. A pattern with user units x="0" y="0" width="20" height="20" and patternUnits="userSpaceOnUse"
To put tiles directly next to one another to fill the area, no matter what its size, without extra padding between tiles, and tiles are cut off only by the edge of the object they're filling you must:
- set
patternUnits="userSpaceOnUse". - specify
x="..." y="..." width="..." height="..."of the tile in user patternUnits.
<svg width="200" height="400" viewBox="0 0 200 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="tile2" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<!-- quadratic curves smoothly connected -->
<path d="M 0 0 Q 5 20 10 10 T 20 20"
style="fill:none; stroke:black;"/>
<!-- square frame -->
<path d=" M 0 0 h 20 v 20 h -20 z" style="
fill:none; stroke:gray;"/>
</pattern>
</defs>
<rect x="20" y="20" width="100" height="100" style="fill:url(#tile2); stroke:black"/>
<rect x="20" y="130" width="70" height="80" style="fill: url(#tile2); stroke: black;"/>
<rect x="20" y="220" width="150" height="130" style="fill: url(#tile2); stroke: black;"/>
</svg>7.1.2 Pattern and patternContentsUnits
patternContentUnits attribute is assigned to units that are to be used to express the pattern data itself. - By default
patternContent Units = "userSpaceOnUse" - If you set the
patternContent Units = "objectBoundingBox", the path data points are expressed in terms of the object being filled. In this case you should draw any objects to be filled with upper left corner of this bounding boxes at the origin (0,0). Also reduce the stroke-width of the pattern data to 0.01, since these units are percentages, not user units.
Example 1 where patternContentUnits = "objectBoundingBox"
<svg width="190" height="380" viewBox="0 0 190 380" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="tile3"
patternUnits="objectBoundingBox"
patternContentUnits="objectBoundingBox"
x="0" y="0" width="0.20" height="0.20">
<path d="M 0 0 Q 0.05 0.20 0.10 0.10 T 0.20 0.20" style="fill:none; stroke:black; stroke-width:0.01;"/>
<path d="M 0 0 h 0.20 v0.20 h -0.20 z" style="fill:none; stroke:black; stroke-width:0.01;"/>
</pattern>
</defs>
<g transform="translate(20,20)">
<rect x="0" y="0" width="100" height="100" style="fill:url(#tile3); stroke:black;"/>
</g>
<g transform="translate(20,140)">
<rect x="0" y="0" width="70" height="80" style="fill:url(#tile3); stroke:black;"/>
</g>
<g transform="translate(20,230)">
<rect x="0" y="0" width="150" height="130" style="fill:url(#tile3); stroke:black;"/>
</g>
Using viewBox for defining a pattern
-
If you want to reduce an existing graphic object for use as a tile, it's easier to use the
viewBox attribute to scale it.
Specifying viewBox attribute to scale it. - Another possible option is to use the preserveAspectRatio attribute, as described in Chapter 2, in Section 2.4. Example 7-5 uses a scaled-down version of the cubic polybézier curve from Figure 6-12 as a tile. The stroke-width is set to 5; otherwise, when scaled down, the pattern would not be visible.
Example 2. Using viewBox to scale pattern
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="tile4"
patternUnits="userSpaceOnUse"
patternContentUnits="userSpaceOnUse"
x="0" y="0" width="20" height="20" viewbox="0 0 150 150">
<path d="M 30 100 C 50 50 70 20 100 100 110 130 50 150 60 100" style="fill:none; stroke:green; stroke-width:5;"/>
</pattern>
</defs>
<rect x="20" y="20" width="100" height="100" style="fill:url(#tile4); stroke:black;"/>
</svg>
7.1.3 Nested Patterns
Example 3. Nested patterns
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="stripe"
patternUnits="userSpaceOnUse"
x="0" y="0" width="6" height="6">
<path d="M 0 0 6 0" style="fill:none; stroke:black;"/>
</pattern>
<pattern id="polkadot"
patternUnits="userSpaceOnUse"
x="0" y="0" width="36" height="36">
<circle cx="12" cy="12" r="12" style="fill:url(#stripe); stroke:black;"/>
</pattern>
</defs>
<rect x="36" y="36" width="96" height="96" style="fill:url(#polkadot); stroke:black;"/>
</svg>