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.
<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.
<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>