nagy.zsolt.hun
nagy.zsolt.hun

Reputation: 6694

vue click animation without setTimeout

I want a div to flash in case a user clicks on it. Is there a solution without manually running setTimeout?

Solution with setTimeout:

app.html

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<style>
div { transition: background-color 1s; }
div.flashing { background-color: green; transition: none; }
</style>

<div id="app" :class="{'flashing':flashing}" v-on:click="flash">flash when clicked</div>

app.js

const data = { flashing: false }

new Vue({
  el: '#app',
  data,
  methods: { flash }
})

function flash() {
  data.flashing = true;
  setTimeout(() => data.flashing = false, 100);
}

Js Fiddle: https://jsfiddle.net/ang3ukg2/

Upvotes: 3

Views: 10003

Answers (2)

Josh Lyon
Josh Lyon

Reputation: 399

Similar to Christopher's answer, but in a way that is more idiomattic to Vue. This uses CSS animation applied via bound classes and the animationend event.

var demo = new Vue({
  el: '#demo',
  data: {
    animated: false
  },
  methods: {
    animate() {
      this.animated = true
    }
  }
})
<link href="https://unpkg.com/[email protected]/animate.min.css" rel="stylesheet" />
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<div id="demo">
  <h1 :class="{'bounce animated': animated}" @animationend="animated = false">
    Animate Test
  </h1>
  <button @click="animate">
    Animate
  </button>
</div>

All credit to Robert Kirsz who proposed the solution in a comment to another question.

Upvotes: 16

Christopher Murphy
Christopher Murphy

Reputation: 101

An alternative is to use CSS animations and hook into the animationend event:

app.html

<div id="app" v-on:click="toggleClass('app', 'flashing')">flash when clicked</div>

app.css

.flashing {
  animation: flash .5s;
}

@keyframes flash {
  0% {
    background-color: none;
  }
  50% {
    background-color: green;
  }
  100% {
    background-color: none;
  }
}

app.js

new Vue({
  el: '#app',

  methods: {
    toggleClass (id, className) {
        const el = document.getElementById(id)
        el.classList.toggle(className)
    }
  },

  mounted () {
    document.getElementById('app').addEventListener('animationend', e => {
        this.toggleClass(e.target.id, 'flashing')
    })
  }
})

Working example: https://jsfiddle.net/Powercube/ang3ukg2/5/

This would allow you to reuse the toggleClass method for other classes without muddying the application with arbitrary class data and timeouts.

You can find more information about animation events at the MDN.

Upvotes: 0

Related Questions