Vue examples

Spring animations

<template>
  <Motion
    :animate="{ rotate: 90, backgroundColor: 'var(--pink)' }"
    :transition="transition"
  />
</template>

<script>
import { Motion } from "motion/vue";
import { spring } from "motion";

export default {
  components: { Motion },
  setup() {
    return {
      transition: {
        delay: 1,
        easing: spring({
          stiffness: 600,
          damping: 12
        }),
      },
    };
  },
};
</script>

<style scoped>
div {
  width: 100px;
  height: 100px;
  border-radius: 10px;
  background-color: var(--green);
}
</style>

Exit animations

<template>
  <div class="container">
    <Presence>
      <Motion
        v-show="show"
        :initial="{ opacity: 0, scale: 0 }"
        :animate="{ opacity: 1, scale: 1 }"
        :exit="{ opacity: 0, scale: 0.6 }"
        class="box"
      />
    </Presence>
    <button @click="show = !show">
      Toggle
    </button>
  </div>
</template>

<script>
import { Motion, Presence } from "motion/vue"

export default {
  components: { Motion, Presence },
  data() {
    return { show: true }
  }
}
</script>

<style>
.container {
  width: 100px;
  height: 150px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.container button {
  cursor: pointer;
}
.box {
  width: 100px;
  height: 100px;
  border-radius: 10px;
  background-color: var(--splash);
}
</style>

Animate between components

<template>
  <div class="container">
    <Presence>
      <Motion
        :key="current"
        :initial="{ opacity: 0, x: 50 }"
        :animate="{
          opacity: 1,
          x: 0,
          transition: { delay: 0.1 }
        }"
        :exit="{ opacity: 0, x: -50 }"
        class="slide"
      >
        {{ current }}
      </Motion>
    </Presence>
    <button @click="current++">
      Next
    </button>
  </div>
</template>

<script>
import { Motion, Presence } from "motion/vue"

export default {
  components: { Motion, Presence },
  data() {
    return { current: 0 }
  }
}
</script>

<style>
.container {
  width: 100px;
  height: 150px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  position: relative;
}

.container button {
  cursor: pointer;
}

.slide {
  width: 100px;
  height: 100px;
  border-radius: 10px;
  background-color: var(--red);
  color: var(--white);
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 72px;
  line-height: 72px;
  font-family: Inter, sans-serif;
  font-weight: 700;
  position: absolute;
  top: 0;
  left: 0;
}
</style>

SVG loading spinner

<template>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
  <g v-for="i in segments" class="segment" :key="i">
    <Motion
      tag="path"
      d="M 94 25 C 94 21.686 96.686 19 100 19 L 100 19 C 103.314 19 106 21.686 106 25 L 106 50 C 106 53.314 103.314 56 100 56 L 100 56 C 96.686 56 94 53.314 94 50 Z"
      :style="{ transform: 'rotate(' + (360 / segments) * i + 'deg)' }"
      :animate="{ opacity: [0, 1, 0] }"
      :transition="{
        offset: [0, 0.1, 1],
        duration,
        delay: i * offset,
        repeat: Infinity,
      }"
    />
  </g>
</svg>
</template>

<script>
import { Motion } from "motion/vue"

export default {
  components: { Motion },
  props: {
    segments: {
      type: Number,
      default: 8
    },
    offset: {
      type: Number,
      default: 0.09
    }
  },
  computed: {
    duration() {
      return this.segments * this.offset
    }
  }
}
</script>

<style>
.segment path {
  opacity: 0;
  transform-origin: 100px 100px;
  fill: var(--splash);
}
</style>

SVG path drawing

<template>
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
  <Motion
    tag="circle"
    cx="100"
    cy="100"
    r="80"
    pathLength="1"
    :animate="draw(1)"
    :transition="{ duration: 0.8, delay: 2 }"
  />
  <Motion
    tag="path"
    d="M 54 107.5 L 88 138.5 L 144.5 67.5"
    pathLength="1"
    :animate="draw(1)"
    :transition="{ duration: 0.6, delay: 2.4 }"
  />
</svg>
</template>

<script>
import { Motion } from "motion/vue"

export default {
  components: { Motion },
  methods: {
    draw: (progress) => ({
      // This property makes the line "draw" in when animated
      strokeDashoffset: 1 - progress,
    
      // Each line will be hidden until it starts drawing
      // to fix a bug in Safari where the line can be
      // partially visible even when progress is at 0
      visibility: "visible",
    })
  }
}
</script>

<style>
circle,
path {
  fill: transparent;
  stroke: var(--green);
  stroke-width: 6px;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  stroke-linecap: round;
  stroke-linejoin: round;
  visibility: hidden;
}

circle {
  transform-origin: 100px 100px;
  transform: rotate(-90deg);
}
</style>

Stay updated with the Motion One newsletter. We don't spam, and unsubscription is instant.