【问题标题】:Shake effect in VueVue中的抖动效果
【发布时间】:2022-09-27 17:42:12
【问题描述】:

我想在 vue.js-application 中创建抖动效果。我找到了一个例子,我可以用它创建一个用JavaScript创建的抖动效果,但是在vue.js中不能使用eventListener-所以我不知道如何在vue.js中使用这段代码。

你知道如何在没有 eventListener 的情况下在 vue.js 中使用这个动画吗?

这是我要调整的代码:

<!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>

  • but the eventListener can\'t be used in vue.js 为什么不呢?也许你做错了。你展示的代码和vuejs没有关系,你怎么知道不能做你想做的

标签: javascript html css vue.js event-listener


【解决方案1】:

基于@Zecka 的解决方案,使用事件监听器而不是超时更好:

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>

在 Vue 中使用事件监听器不是问题@Florian27,您可以通过添加 ref 属性或简单地使用document.querySelector 甚至更好的this.$el.querySelector 轻松定位组件中的任何元素,以便将其范围限定为您的组件,然后附加一个事件使用纯 JS 的监听器。

【讨论】:

  • 非常感谢您的快速答复。它工作得很好!另一个问题:我有不止一个对象。如果我单击一个对象,所有对象都会被摇动,但我只想摇动我刚刚单击的对象。你也有这个问题的答案吗?我的想法是只调用一个具有特定 ID 的对象,但在我的示例中每次都不起作用。也许你有更好的想法。
【解决方案2】:

在您的示例中,事件侦听器所做的唯一事情就是切换一个类。
所以你可以使用条件类语法&lt;button :class="{'apply-shake': shake}"&gt;;

检查代码框:https://codesandbox.io/s/shake-effect-vue-71306745-z912ms?file=/src/App.vue

所以你可以做这样的事情:

编辑:检查 @quadmachine answer 谁使用 eventListener for animationend 而不是 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>


【讨论】:

    【解决方案3】:
            //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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      • 1970-01-01
      • 2016-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多