Search code examples
vue.jsvuejs3web-animations-api

How to use Web Animations API with Vue


The Vue3 docs uses css to efffect transitions, but I wanted to try the (relatively new) Web Animations API instead - partly because I have trouble using variables in CSS.

The following code works:

<script setup>
import { ref } from 'vue'
import comp from './comp.vue'

function moveCircle() {
  let elem = document.getElementById("circle");
  if (elem) {
    elem.animate(
      [
        { transform: "translateX(0px)"},
        { transform: "translateX(320px)"}
      ], 500
    )
  }
}
</script>

<template>
<div>
  <comp id="circle"></comp>
  <button @click="moveCircle()">Move it</button>
</div>
</template>

(comp)

<script setup></script>

<template>
  <svg width="100" height="100">
    <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
  </svg>
</template>

Vue playground here

... but I wanted to get rid of the somewhat cumbersome getElementById and instead use Vue template refs :

<script setup>
import { ref } from 'vue'
import comp from './comp.vue'

const circle = ref(null);

function moveCircle() {

  let elem = circle.value;
  if (elem) {
    elem.animate(
      [
        { transform: "translateX(0px)"},
        { transform: "translateX(320px)"}
      ], 500
    )
  }
}
</script>

<template>
<div>
  <comp ref="circle"></comp>
  <button @click="moveCircle()">Move it</button>
</div>
</template>

but this does not do the animation (revised playground). At one point I had an error animate() is not a function but now there is no error - just nothing happens. What's the correct way to do this?


Solution

  • Because it's a ref to a component, circle.value gives you the component instance which is evident when you console.log it. To access the root DOM node of the component, use circle.value.$el. Documentation reference

    Updated Vue Playground