Skip to content

Animation with svelte/motion

You can animate using svelte/motion just like you would in other Svelte application.

Spring

<script>
  import * as PIXI from 'pixi.js'
  import { Text, Sprite } from 'svelte-pixi'
  import { spring } from 'svelte/motion'

  let dragging = false
  let offset = { x: 0, y: 0 }
  let startingPosition = { x: 0, y: 0 }

  let position = spring(startingPosition, {
    stiffness: 0.2,
    damping: 0.4,
  })

  function handleDragStart(event) {
    dragging = true
    const { x, y } = event.detail.data.global

    offset = {
      x: x - $position.x,
      y: y - $position.y,
    }
  }

  function handleDrag(event) {
    if (dragging) {
      const { x, y } = event.detail.data.global
      position.update(
        ($position) => ({
          x: x - offset.x,
          y: y - offset.y,
        }),
        { hard: true },
      )
    }
  }

  function handleDragEnd() {
    dragging = false
    position.set(startingPosition, { soft: 1 })
  }
</script>

<Sprite
  texture={PIXI.Texture.from('/assets/mushroom.png')}
  anchor={0.5}
  x={$position.x}
  y={$position.y}
  rotation={($position.x - startingPosition.x) * 0.02}
  eventMode="static"
  cursor="pointer"
  zIndex={10}
  on:pointerdown={handleDragStart}
  on:pointerup={handleDragEnd}
  on:pointerupoutside={handleDragEnd}
  on:globalpointermove={handleDrag}
/>

<Text
  y={100}
  anchor={0.5}
  text="Try clicking and dragging the mushroom"
  style={{ fill: 'white', fontSize: 20 }}
/>

Tween

<script>
  import { onMount } from 'svelte'
  import { Graphics, onTick } from 'svelte-pixi'
  import { tweened } from 'svelte/motion'
  import { cubicOut } from 'svelte/easing'

  const barWidth = 200

  const progress = tweened(barWidth / 5, {
    duration: 400,
    easing: cubicOut,
  })

  let step = 0

  onTick(() => {
    step += 1

    if (step > 100) {
      step = 0

      if ($progress < barWidth) {
        $progress += barWidth / 5
      } else {
        $progress = barWidth / 5
      }
    }
  })
</script>

<Graphics
  pivot={{ x: barWidth / 2 }}
  draw={(graphics) => {
    graphics.clear()
    graphics.beginFill(0xff0000)
    graphics.drawRect(0, 0, $progress, 50)
    graphics.endFill()
  }}
/>