Home > Back-end >  Shake effect in Vue
Shake effect in Vue

Time:03-02

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.

  • Related