packages/lit-dev-content/site/tutorials/content/svg-templates/03.md
This section of the tutorial covers the basics of <clipPath> and
<g> elements in SVG including how to:
<use>In pattern making, a tile is a polygon that can be repeated across a two dimensional plane. The tile in this demo will be a series of transformed texts.
Clip paths are polygons used to restrict where elements are "painted".
In SVG, a clip path is defined with the <clipPath>
element.
In the example below, a clip path will be created in the shape of a
rectangle with an id of rect-clip.
const helloClipPath = svg`
<clipPath id="rect-clip">
<rect width="200" height="200"></rect>
</clipPath>
`;
In order to apply a clip path to an SVG element, the clip-path
property should reference a <clipPath> element by an id. The
<rect> below will be clipped by the clip-path above by referencing
#react-clip.
const helloTile = svg`
<rect
clip-path="url(#rect-clip)"
width="300"
height="300"
fill="#000000">
</rect>
Use <clipPath> to create a 200px square tile. This <clipPath> will
restrict anything painted inside of it to its 200px square boundaries. Give
the clip-path an id called rect-clip.
const createTileBoundary = () => svg`
<clipPath id="rect-clip">
<rect width="200" height="200"></rect>
</clipPath>
`;
Then give the <g> returned by createMotif an id called motif.
{% switchable-sample %}
const createMotif = (
numPrints: number,
offset: number = 0,
): SVGTemplateResult => {
...
return svg`
<g
id="motif"
transform="translate(50, 50)">
${prints}
</g>
`;
}
const createMotif = (
numPrints,
offset = 0,
) => {
...
return svg`
<g
id="motif"
transform="translate(50, 50)">
${prints}
</g>
`;
}
{% endswitchable-sample %}
After, move the createMotif inside <defs>.
export class RepeatPattern extends LitElement {
...
render() {
return html`
<svg height="100%" width="100%">
<defs>
${createTileBoundary()}
${createElement(this.chars)}
${createMotif(
this.numPrints,
this.rotationOffset,
)}
</defs>
</svg>
`;
}
}
Make a function called createTile. This function will utilize the motif
and clipPath now available in <defs> by referencing #motif in a
<use> element, and url(#rect-clip) in the clip-path attribute.
const createTile = () => svg`
<g clip-path="url(#rect-clip)">
<use transform="translate(0, 0)" href="#motif"></use>
<use transform="translate(0, 100)" href="#motif"></use>
<use transform="translate(100, -50)" href="#motif"></use>
<use transform="translate(100, 50)" href="#motif"></use>
<use transform="translate(100, 150)" href="#motif"></use>
</g>
`;
Finally, call createTile inside the svg element during render.
export class RepeatPattern extends LitElement {
...
render() {
return html`
<svg height="100%" width="100%">
...
${createTile()}
</svg>
`;
}
}
This demo composes a tile containing five groups of rotated text to create a seamless offset for repitition. However, placement and count is arbitrary.
Try different variations! The createTile function will be the
foundation of future patterns.
After completing this section, you'll be ready to learn how create
repeat patterns using the <pattern> element.