首先展示一下效果,狠狠点击 https://zhangkunusergit.github.io/vue-component/dist/jitter.html

代码github : https://github.com/zhangKunUserGit/vue-component

 转载请标注: https://www.cnblogs.com/zhangkunweb/p/vue_jitter.html

先说一下用法:

  1. <jitter :start.sync="抖动控制器" :range="{ 包含x,y, z }" :shift-percent="0.1">
  2. 这里是你要抖动的元素
  3. </jitter>

思路:

1.抖动就是摆动,现实中的钟摆可以很形象。

2.当摆动到临界点后,就会向相反的方向摆动。

3.在没有动力时,摆动会慢慢停止。

初始化抖动:

  1. /**
  2. * 初始化抖动
  3. */
  4. initJitter() {
  5. // 把start变成false, 方便下次点击
  6. this.$emit('update:start', false);
  7. // 清除上次动画
  8. this.clearAnimate();
  9. // 设置currentRange, 填充this.range 中没有的项
  10. this.currentRange = Object.assign({}, { x: 0, y: 0, z: 0 }, this.range);
  11. // 获取需要操作的的项 和 每次需要摆动的量
  12. const { position, shiftNumber } = this.getPositionAndShiftNumber();
  13. this.position = position;
  14. this.shiftNumber = shiftNumber;
  15. // 初始 move 起始点是0
  16. this.move = { x: 0, y: 0, z: 0 };
  17. // 初始时 是顺时针
  18. this.isClockwise = true;
  19. // 执行动画
  20. this.timer = window.requestAnimationFrame(this.continueJitter);
  21. },

这里准备动画开始前的工作。

执行动画:

  1. // 持续抖动
  2. continueJitter() {
  3. this.refreshMove(this.isClockwise ? -1 : 1);
  4. // 绝对值
  5. const absMove = this.getAbsMove();
  6. const currentRange = this.currentRange;
  7. let changeDirection = false;
  8. for (let i = 0, l = this.position.length, p; i < l; i += 1) {
  9. p = this.position[i];
  10. // 判断是否到达临界值,到达后 应该反方向执行动画
  11. if (currentRange[p] <= absMove[p]) {
  12. // 等比例缩减
  13. this.currentRange[p] -= this.shiftNumber[p];
  14. // 判断如果已经无力再摆动,就让摆动停止, 只要有一个值达到了0,所有都会达到
  15. if (this.currentRange[p] <= 0) {
  16. // 停止在起始点上
  17. this.jitterView({ x: 0, y: 0, z: 0 });
  18. // 清除动画
  19. this.clearAnimate();
  20. return;
  21. }
  22. // 更新move为临界点
  23. this.move[p] = this.isClockwise ? -this.currentRange[p] : this.currentRange[p];
  24. // 改变摆动方向
  25. changeDirection = true;
  26. }
  27. }
  28. if (changeDirection) {
  29. // 摆动方向取反
  30. this.isClockwise = !this.isClockwise;
  31. }
  32. // 更新元素位置
  33. this.jitterView(this.move);
  34. // 继续执行动画
  35. this.timer = window.requestAnimationFrame(this.continueJitter);
  36. },

执行动画,当判断已经无力摆动后,让元素回归到原来的位置,并清除动画。

修改元素位置:

  1. /**
  2. * 修改元素位置
  3. * @param x
  4. * @param y
  5. * @param z
  6. */
  7. jitterView({ x = 0, y = 0, z = 0 }) {
  8. this.$el.style.transform = `translate3d(${x}px, ${y}px, ${z}px)`;
  9. },

这里需要判断需要 Z 轴摆动吗? 当需要时,必须给当前元素的父级添加 perspective, 从而修改子级透视效果

  1. mounted() {
  2. // 如果要执行 z 轴动画需要设置父级,从而修改子级透视效果,否则 Z 轴没有效果
  3. if (this.range.z > 0) {
  4. const parentEl = this.$el.parentNode;
  5. Object.keys(this.perspectiveStyle).forEach((key) => {
  6. parentEl.style[key] = this.perspectiveStyle[key];
  7. });
  8. }
  9. },

最后看看可以传的属性:

  1. props: {
  2. // 抖动范围,单位是px, 例如:{x: 4, y: 2, z: 10}
  3. range: {
  4. type: Object,
  5. default: () => { return { z: 8 }; },
  6. },
  7. start: {
  8. type: Boolean,
  9. required: true,
  10. },
  11. shiftPercent: {
  12. type: Number,
  13. default: 0.1, // 移动range中初始值的百分比
  14. },
  15. perspectiveStyle: {
  16. type: Object,
  17. default: () => {
  18. return {
  19. perspective: '300px',
  20. perspectiveOrigin: 'center center'
  21. };
  22. }
  23. }
  24. },

上面是可以传的属性,大家可以按照情况修改

最后:

这里我只写了简单的动画,也可以根据不同情况进行修改,从而达到想要的效果。这里已经满足输入框错误抖动的效果了。

版权声明:本文为zhangkunweb原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zhangkunweb/p/vue_jitter.html