Spin In

transform

The whole drawing spins in from a half-turn back while it grows, overshooting slightly before it settles.

Demo shape

Every animation on the page redraws with the shape you pick.

Align
Ease
Duration
s
0.13
Stagger
s
00.2
Delay
s
02
<!-- 1. Markup -->
<svg viewBox="0 0 120 120" class="k-spin-in" aria-hidden="true">
  <circle cx="60" cy="60" r="34" fill="none" stroke="currentColor" stroke-width="8" vector-effect="non-scaling-stroke" />
  <line x1="60" y1="12" x2="60" y2="38" stroke="currentColor" stroke-width="8" stroke-linecap="round" vector-effect="non-scaling-stroke" />
  <line x1="60" y1="82" x2="60" y2="108" stroke="currentColor" stroke-width="8" stroke-linecap="round" vector-effect="non-scaling-stroke" />
  <circle cx="60" cy="60" r="10" fill="currentColor" />
</svg>

// 2. JS
function spinIn(svg) {
  const _reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
  const _duration = _reducedMotion ? 0.01 : 0.8
  const _delay = _reducedMotion ? 0 : 0

  // One group around the whole drawing, so it turns about its own centre as a
  // single piece. A <title> stays where it is: it names the <svg>, and moving
  // it into a group would take that name away.
  const group = document.createElementNS('http://www.w3.org/2000/svg', 'g')
  group.append(...[...svg.children].filter((el) => el.tagName !== 'title'))
  svg.append(group)
  // Without fill-box the group would turn about the SVG's top-left corner.
  group.style.transformBox = 'fill-box'
  group.style.transformOrigin = 'center'
  const animation = group.animate([{ transform: 'rotate(-180deg) scale(0)' }, { transform: 'rotate(0deg) scale(1)' }], {
    duration: _duration * 1000,
    delay: _delay * 1000,
    easing: 'linear(0.0000,0.0729,0.1426,0.2090,0.2724,0.3327,0.3900,0.4444,0.4960,0.5447,0.5908,0.6343,0.6752,0.7136,0.7496,0.7832,0.8145,0.8437,0.8707,0.8956,0.9185,0.9395,0.9587,0.9760,0.9916,1.0056,1.0180,1.0289,1.0384,1.0465,1.0532,1.0588,1.0632,1.0665,1.0688,1.0701,1.0706,1.0702,1.0691,1.0674,1.0650,1.0622,1.0588,1.0551,1.0511,1.0468,1.0423,1.0377,1.0331,1.0285,1.0241,1.0198,1.0157,1.0120,1.0086,1.0057,1.0033,1.0015,1.0004,1.0000)',
    fill: 'both',
  })

  return () => {
    animation.cancel()
    group.replaceWith(...group.childNodes)
  }
}


spinIn(document.querySelector('.k-spin-in'))