| <!DOCTYPE html> |
| <html> |
| <button id="dotsbutton" style="border: 0; background: transparent; padding: 0;"> |
| <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 9 9" id="dots"> |
| <rect x="4" y="4" width="1" height="1" rx=".5" ry=".5" fill="#4285f4" style="transform-origin: 50%; will-change: transform;"></rect> |
| <rect x="4" y="4" width="1" height="1" rx=".5" ry=".5" fill="#ea4335" style="transform-origin: 50%; will-change: transform;"></rect> |
| <rect x="4" y="4" width="1" height="1" rx=".5" ry=".5" fill="#faBB05" style="transform-origin: 50%; will-change: transform;"></rect> |
| <rect x="4" y="4" width="1" height="1" rx=".5" ry=".5" fill="#34a853" style="transform-origin: 50%; will-change: transform;"></rect> |
| </svg> |
| </button> |
| <script> |
| var dots = Array.prototype.slice.call(document.getElementsByTagName('rect')); |
| |
| function getLineOffsetX(dotIndex) { |
| return -3 + dotIndex * 2; |
| } |
| |
| function transitionTo(dotIndex, transform, duration = 150, delay = 0) { |
| const dot = dots[dotIndex]; |
| const originalTransform = getComputedStyle(dot).getPropertyValue('transform'); |
| const animation = dot.animate([ |
| { transform: originalTransform }, |
| { transform }, |
| ], { |
| easing: 'cubic-bezier(.0,.0,.2,1)', |
| fill: 'both', |
| delay, |
| duration, |
| }); |
| } |
| |
| function showListening() { |
| const LATENCY_PER_DOT_MS = 200; |
| for (let i = 0; i < dots.length; i++) { |
| const offsetX = getLineOffsetX(i); |
| transitionTo(i, `translateX(${offsetX}px)`, 150 + i * LATENCY_PER_DOT_MS); |
| } |
| } |
| |
| showListening(); |
| </script> |
| </html> |