One of the strengths of SVG is the ability to easily reuse graphics and transform each instance in a different way. A graphic like this:
is really a <pattern>
consisting of just 23 lines of code with various animations, clippaths and transformations applied to it.
A <pattern> is "defined" in the <defs> section at the beginning of the SVG. The basic framework for the pattern looks like this:
<svg> <defs> <pattern id="myPattern" x="0" y="0" width="50" height="50" patternUnits="userSpaceOnUse"/> "YOUR-PATHS-HERE"" </pattern> </defs> <rect width="100" height="100" fill="url(#myPattern)"/> </svg>
Imagine you have a bathroom floor tile that is 50 pixels wide and 50 pixels high. Regardless of the size of the picture on the tile, the tile itself is 50x50. That is the <pattern> we defined above. The 100x100 <rect> is like four tiles laid next to each other in a 2-tile by 2-tile square. You can make the <rect> as large or small as you want, and it will use as many tiles (or pieces of tiles) as it needs to cover the space you have specified.
You can also use other shapes, like <path>, <polygon> or <circle>. In this demo, I used
<circle cx="160" cy="160" r="160" fill="url(#psea)" />
This created a 320-pixel wide (r="160" defines the radius as 160 pixels) filled with my pattern. "psea" is my shorthand for Pattern SEA. I was working on a pen with an animated sea, and as I tinkered with the animation I came up with these animations.
The rotations here are actually done by CSS.
<g> <circle cx="160" cy="160" r="160" fill="url(#psea)" > <animateTransform attributeName="transform" begin="0s" dur="2.5s" type="rotate" from="360 160 160" to="0 160 160" repeatCount="indefinite"/> </circle> </g>
SMIL animates the CSS transform rotation from 360 degrees to 0 degrees (counterclockwise; from 0 to 360 would rotate clockwise) around the point 160,160. It's like taking a paper cutout of the circle, putting a pin through it at coordinates 160,160 (the center of my circle, which has the attributes cx="160" and cy="160") and spinning it. If you put the pin in a different location, like top left corner (0,0), it would spin around that, so pay close attention to the coordinates of that pin.
I only wanted to show one quarter of my circle at a time, creating a wedge shape like a pizza slice, and just to make things interesting I spun that shape in the opposite direction of the pattern's movement.
First I defined my clippath in the defs section as a square covering the top left corner of the SVG.
<clipPath id="quadrant1"> <path d="M0,0 160,0 160,160 0,160z"/> </clipPath>
Then I applied the clip path to the group (<g>) that contains the circle.
<g style="clip-path:url(#quadrant1);"> <circle cx="160" cy="160" r="160" fill="url(#psea)" > <animateTransform attributeName="transform" begin="0s" dur="3s" type="rotate" from="360 160 160" to="0 160 160" repeatCount="indefinite"/> </circle> <animateTransform attributeName="transform" begin="0s" dur="6s" type="rotate" from="0 160 160" to="360 160 160" repeatCount="indefinite"/> </g>
Because the group is spinning in one direction and the circle inside it is spinning in the opposite direction, the circle has to spin twice as fast (dur="3s" instead of dur="6s") to travel the same speed as the clip path. If both were set to 3s, the two rotations would cancel each other out and the circle would appear stationary while the clip path moved.
A second circle moving in the opposite direction of the first, and a clip path in the opposite corner rotating just like the first clip path round out the animation for an interesting effect.
Adding More Instances and Complexity
In a fork of the pen above, I created the illusion of sea swell by splitting the polygons in the pattern into two groups and animating the opacity of the groups on alternate frequencies.
In another fork, one of the circles was actually rendered as a small circle and layered on the wedge.
You can keep reusing the pattern, and the shapes you have created from it, to make complex animations with very little code.