I would like to create a shake effect in a vue.js-application. I found an example, with which I can create create a shake effect with JavaScript, but the eventListener can't be used in vue.js- So I do not know how to use this code in vue.js.
Do you have any idea how I could use this animation in vue.js without an eventListener?
Here is the code, which I want to adjust:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="./main.css">
<title>3d Vector Kata</title>
<style>
/* Standard syntax */
@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;
}
</style>
</head>
<body>
<form id="test-form">
<input type="text" id="test-input">
<button type="submit" id="submit-button" onclick="shakeAnimation()">Submit</button>
</form>
<script src="./index.js"></script>
</body>
</html>
<script>
const input = document.querySelector("input#test-input");
const submit = document.querySelector("button#submit-button");
submit.addEventListener("click", (e) => {
e.preventDefault();
if(input.value === "") {
submit.classList.add("apply-shake");
}
});
submit.addEventListener("animationend", (e) => {
submit.classList.remove("apply-shake");
});
</script>
CodePudding user response:
The only things that event listener do in your example is to toggle a class.
So you can use conditional class syntax <button :>
;
Check on codesandbox: https://codesandbox.io/s/shake-effect-vue-71306745-z912ms?file=/src/App.vue
So you can do something like that:
<template>
<div id="app">
<button : @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>
CodePudding user response:
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.