有时候需求就是这么奇怪,要求鼠标移动到组件上面有一个动画回弹效果
组件代码如下(ts写法)
1 <template> 2 <div @mouseover="onMouseover" @mouseout="onMouseout"> 3 <el-progress 4 v-bind="$attrs" 5 :percentage="showPercentage" 6 v-on="$listeners" 7 ></el-progress> 8 </div> 9 </template> 10 <script lang="ts"> 11 import { Component, Vue, Watch, Prop } from "vue-property-decorator"; 12 /** 13 * 14 * el-progress组件增强 15 * 当鼠标移动到组件上时会触发一个动画效果 16 * 17 * 用法和el-progress一样 18 * 19 */ 20 @Component({ 21 name: "ZbProgress" 22 }) 23 export default class ZbProgress extends Vue { 24 // 百分比 25 @Prop() percentage!: any; 26 // 监听百分比数值 27 @Watch("percentage", { immediate: true }) 28 updatePercentage(v: number) { 29 // 因为需要通过改变百分比来实现动画效果 30 // 所以这里将具体值赋值给一个内部字段 31 this.showPercentage = v; 32 } 33 // 动画执行时间(毫秒) 34 @Prop({ default: 200 }) animationTime!: number; 35 // 动画波动百分比变化范围 36 // 可以为负值 37 @Prop({ default: 30 }) animationRange!: number; 38 // 百分比显示值 39 showPercentage: number = 0; 40 41 // 是否正在执行动画 42 isAnimationIng: boolean = false; 43 // 上传鼠标离开元素时间 44 outTime: number = 0; 45 // 当鼠标移动到元素内时 46 onMouseover() { 47 // console.log("onMouseover鼠标移动到"); 48 // 获取鼠标上次离开时间 49 const outTime = this.outTime; 50 // 是否执行动画 51 let is = true; 52 if (outTime) { 53 // 如果上次离开时间与当前时间间隔太短 54 // 说明鼠标并没有真正的离开当前元素,只是在内部移动 55 // 此时不执行动画 56 is = new Date().getTime() - outTime > 100; 57 } 58 if (is) { 59 // 执行动画 60 this.showAnimation(this.showPercentage); 61 } 62 } 63 // 当鼠标离开时 64 onMouseout() { 65 // console.log("onMouseout鼠标离开"); 66 // 记录当前离开时间 67 this.outTime = new Date().getTime(); 68 } 69 // 执行动画 70 showAnimation(v: number) { 71 const me = this as any; 72 // 如果没用正在执行动画 73 if (!me.isAnimationIng) { 74 // 标识动画效果正则执行 75 me.isAnimationIng = true; 76 const { 77 // 动画波动百分比变化范围 78 animationRange, 79 // 动画执行时间(毫秒) 80 animationTime 81 } = me; 82 // 获取下个动画波动值 83 let percentage = v - animationRange; 84 // 将波动值限制到0-100 85 if (percentage <= 0) { 86 percentage = 0; 87 } else if (percentage >= 100) { 88 percentage = 100; 89 } 90 // 设置动画波动值 91 me.showPercentage = percentage; 92 setTimeout(() => { 93 // 延迟执行重置百分比,这样就能实现一个波动动效 94 me.showPercentage = v; 95 setTimeout(() => { 96 // 延迟标识动画效果已经结束 97 me.isAnimationIng = false; 98 }, 200); 99 }, animationTime); 100 } 101 } 102 } 103 </script>
使用
<template> <div> <zb-progress :show-text="false" :stroke-width="26" :percentage="70" :animationRange="-30"> </zb-progress> <br /> <zb-progress :show-text="false" :stroke-width="26" :percentage="30"> </zb-progress> <br /> <zb-progress :show-text="false" :stroke-width="26" :percentage="15" :animationTime='1000'> </zb-progress> </div> </template> <script lang="ts"> import { Component, Vue } from "vue-property-decorator"; @Component({ name: "elementProgress" }) export default class elementProgress extends Vue {} </script>