Motion

What Is Motion?

Animotion is great for animating layouts and code blocks, but Motion is the missing piece for doing animations.

Instead of being limited to animating CSS properties using a JavaScript animation library, or the Web Animations API , it uses values that change over time.

Animating Values

You can use a signal to create a value that changes over time.

Animate the value using the to method, and use the await keyword to start the animation. The next animation only plays once the previous animation is done. You can chain multiple to methods together.

<script lang="ts">
  import { Presentation, Slide } from '@components'
  import { signal } from '@motion'

  let circleX = signal(0)

  async function animate() {
    await circleX.to(400).to(0)
  }
</script>

<Presentation>
  <Slide on:in={animate}>
    <svg viewBox="0 0 400 400">
      <circle cx={$circleX} cy={200} r={100} fill="#00ffff" />
    </svg>
  </Slide>
</Presentation>

You can animate any value, including CSS properties using the style tag, or Svelte's style: directive.

Motion

<script lang="ts">
  import { Presentation, Slide } from '@components'
  import { signal } from '@motion'

  let textScale = signal(1)

  async function animate() {
    await textScale.to(3).to(1)
  }
</script>

<Presentation>
  <Slide on:in={animate}>
    <!-- Using the style attribute -->
    <h1 style="scale: {$textScale}">Motion</h1>

    <!-- Svelte shorthand -->
    <h1 style:scale={$textScale}>Motion</h1>
  </Slide>
</Presentation>

Animating Multiple Values

A signal can be a single value, or an object which can interpolate between strings, objects, and arrays — it also accepts an options object that includes a duration, delay, and easing option, and override the options for each animation.

<script lang="ts">
  import { Presentation, Slide } from '@components'
  import { signal } from '@motion'

  let circle = signal({ x: 0, fill: '#00ffff' }, { duration: 1500 })

  async function animate() {
    await circle
      .to({ x: 400, fill: '#ffff00' }, { delay: 300 })
      .to({ x: 0, fill: '#00ffff' })
  }
</script>

<Presentation>
  <Slide on:in={animate}>
    <svg viewBox="0 0 400 400">
      <circle cx={$circle.x} cy={200} r={100} fill={$circle.fill} />
    </svg>
  </Slide>
</Presentation>

Combining Animations

You can animate different signals at the same using the all method.

0
<script lang="ts">
  import { Presentation, Slide } from '@components'
  import { signal, all } from '@motion'

  let circle = signal({ x: 0, y: 200, r: 100, fill: '#00ffff' })
  let text = signal({ count: 0 })
  
  async function animate() {
    all(
      circle
        .to({ x: 400, fill: '#ffff00' })
        .to({ x: 0, fill: '#00ffff' }),
      text.to({ count: 400 }).to({ count: 0 })
    )
  }
</script>

<Presentation>
  <Slide on:in={animate}>
    <svg viewBox="0 0 400 400">
      <circle
        cx={$circle.x}
        cy={$circle.x}
        r={$circle.r}
        fill={$circle.fill}
      />
      
      <text
        x={$circle.x}
        y={$circle.y}
        font-size={$circle.r * 0.4}
        text-anchor="middle"
        dominant-baseline="middle"
      >
        {$text.count.toFixed(0)}
      </text>
    </svg>
  </Slide>
</Presentation>

Playing Sounds

Besides playing animations you can play sounds using the sfx method.

After you place your sounds in the public folder at the root of your project, they become available from the root path / of your site.

<script lang="ts">
  import { Presentation, Slide } from '@components'
  import { signal } from '@motion'

  let circle = signal({ x: 0 })
  
  async function animate() {
    await circle
      .sfx('/sfx/transition.mp3')
      .to({ x: 400 })
  }
</script>

<Presentation>
  <Slide on:in={animate}>
    <svg viewBox="0 0 400 400">
      <circle cx={$circle.x} cy={200} r={100} fill="#00ffff" />
    </svg>
  </Slide>
</Presentation>

Animation Reset

If you mess up your delivery, instead of reloading the slide to reset the state of your animation, use the reset method on the signal to reset the animation back to its initial state.

<script lang="ts">
  import { Presentation, Slide } from '@components'
  import { signal } from '@motion'

  let value = signal(0)
</script>

<Presentation>
  <Slide on:out={() => value.reset()}>
    <!-- ... -->
  </Slide>
</Presentation>