Now that I have an SVG image, that is, the site logo, it might be time to explore more ways to mess with SVG images.
So, what if I want to create a “spinner” based on the site logo?
The reference implementation
The Angular Material component library does contain an SVG-based spinner.
A question to ask is: how can they animate the starting point and ending point of the arc, when the SVG circle element does not actually provide attributes for that?
The answer is somewhat surprising: they don’t draw an arc; they draw a circle in dashed line. It just happens that the dashed line has the period length equal to the perimeter of the circle.
<circle
*ngSwitchCase="true"
cx="50%"
cy="50%"
[attr.r]="_circleRadius"
[style.animation-name]="'mat-progress-spinner-stroke-rotate-' + diameter"
[style.stroke-dashoffset.px]="_strokeDashOffset"
[style.stroke-dasharray.px]="_strokeCircumference"
[style.stroke-width.%]="_circleStrokeWidth"></circle>
CSS Animation
While the reference implementation uses Angular, it is because it tries to provide a complex API: one could control the size of the circle, the width of the line, and switch between determinate mode and indeterminate mode, etc.
For a simple example, implementing a spinner does not involve any Javascript code. I just needed to embed a CSS animation in it. Here is the code:
<svg width="64mm" height="64mm" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<style type="text/css">
@keyframes rotate {
0% { stroke-dashoffset: 0;}
100% { stroke-dashoffset: 160.5874481201172;}
}
path {
animation: rotate 2s linear 0s infinite;
}
</style>
</defs>
<g>
<path d="m32.585 22.364 6.1468 0.254 0.762 4.1148 3.9624 0.254c0.6096-2.9972 0.9652-6.096 0.9652-9.144l-0.508-0.508h-24.028l-0.254 2.9464c1.1684 0.508 2.4384 0.9652 3.81 1.27v25.806c-1.3716 0.3048-2.6416 0.762-3.81 1.27v
2.7432h18.288l0.254-2.7432-6.096-0.508c0.4064-2.3368 0.508-4.6228 0.508-7.1628v-4.318l8.89 0.9652c0.254-2.2352 0.254-4.0132 0-6.2484l-8.89 0.9652z" fill="none" stroke="#000"
stroke-dasharray="60.5874481201172 100"
stroke-dashoffset=0
/>
</g>
</svg>
It should be self-evident how it works.
However, where does I get the magical number 160.5874481201172
, that is, the perimeter of the weird “F” shape?
Getting the perimeter
A quick Google search leads to this StackOverflow discussion. Essentially, what works is the following code:
var myPath = document.getElementById("word");
var length = myPath.getTotalLength();
console.log(length);
By using Javascript to dynamically get the perimeter, one avoids the magical numbers in the code. The downside is that there is now Javascript code to maintain.
OK. Now I am back on the Angular track, and this is now maintained as an Angular component.