2👍
The only things that event listener do in your example is to toggle a class.
So you can use conditional class syntax <button :class="{'apply-shake': shake}">
;
Check on codesandbox: https://codesandbox.io/s/shake-effect-vue-71306745-z912ms?file=/src/App.vue
So you can do something like that:
Edit: Check @quadmachine answer who use eventListener for animationend instead of setTimeout
<template>
<div id="app">
<button :class="{ 'apply-shake': shake }" @click="shakeAnimation()">
Shake
</button>
</div>
</template>
<script>
export default {
data() {
return {
shake: false,
};
},
methods: {
shakeAnimation() {
this.shake = true;
setTimeout(() => {
this.shake = false;
}, 820); // timeout value depending on the duration of the animation
},
},
};
</script>
<style>
@keyframes shake {
10%,
90% {
transform: translate3d(-1px, 0, 0);
}
20%,
80% {
transform: translate3d(2px, 0, 0);
}
30%,
50%,
70% {
transform: translate3d(-4px, 0, 0);
}
40%,
60% {
transform: translate3d(4px, 0, 0);
}
}
.apply-shake {
animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}
</style>
2👍
Building on @Zecka’s solution, even better to use an event listener instead of a timeout:
https://codesandbox.io/s/shake-effect-vue-71306745-forked-hebrob?file=/src/App.vue:471-754
<script>
export default {
data() {
return {
shake: false,
};
},
mounted() {
this.$refs.submit.addEventListener("animationend", () => {
this.shake = false;
});
},
methods: {
shakeAnimation() {
this.shake = true;
},
},
};
</script>
Using event listeners in Vue is not an issue @Florian27, you can target any element in your component easily by adding ref attribute or simply by using document.querySelector
or even better this.$el.querySelector
so that it’s scoped to your component and then attach an event listener using pure JS.
0👍
//shake.css
@keyframes shake {
10%, 90% {
transform: translate3d(-1px, 0, 0);
}
20%, 80% {
transform: translate3d(2px, 0, 0);
}
30%, 50%, 70% {
transform: translate3d(-4px, 0, 0);
}
40%, 60% {
transform: translate3d(4px, 0, 0);
}
}
.apply-shake {
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both !important;
}
//shake.js
import '@/assets/css/shake.css';
export const shake = app => {
app.directive('shake', {
mounted: el => {
//节流
let shakeOver = true;
el.addEventListener(
'click',
e => {
if (shakeOver) {
shakeOver = false;
e.target.classList.add('apply-shake');
let timer = setTimeout(() => {
clearTimeout(timer);
e.target.classList.remove('apply-shake');
shakeOver = true;
}, 820);
}
},
false
);
}
});
};
//main.js
import { createApp } from 'vue';
import App from './App.vue';
import {shake} from '@/directives/shake.js'
const app = createApp(App);
shake(app);
app.mount('#app');
//please use vue3.x
//use example:
<h1 v-shake>click me</h1>
- [Vuejs]-Updating data in multiple places without reloading the page
- [Vuejs]-Using external variable in webpack bundle