记录–仿加入购物车飞入动画效果

  • 记录–仿加入购物车飞入动画效果已关闭评论
  • 108 次浏览
  • A+
所属分类:Web前端
摘要

近期对管理后台相关功能进行优化,其中导出功能涉及到查询数据过多导致查询很慢问题,决定采用点击后加入到下载中心方式,既解决了接口慢等待问题,也方便后期各种文件的重复下载,一举多得~


这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录--仿加入购物车飞入动画效果

近期对管理后台相关功能进行优化,其中导出功能涉及到查询数据过多导致查询很慢问题,决定采用点击后加入到下载中心方式,既解决了接口慢等待问题,也方便后期各种文件的重复下载,一举多得~

功能上很好实现,调接口就可以了,主要涉及到一个小球飞入效果,基础原理和商城的加入购物车很像,就是点击按钮之后,出现一个小球,按照一定路径飞入固定位置。先来看下基本的原理图:

记录--仿加入购物车飞入动画效果

最终效果就是,点击按钮,出现小球按照红色线路径飞入到下载中心位置。通过原理图,我们也可以看出。只要知道两个元素的位置差,然后通过一定属性控制动画路径就可以了,这里采用了css3的transfrom动画。

两个元素的位置差:

获取位置差x轴:下载中心.left - 按钮.clientX

获取位置差y轴:下载中心.top - 按钮.clientY

其中按钮的相关属性,可以在点击时通过$event去获取。

下载中心相关属性,通过ref?.value?.getBoundingClientRect()获取。同时这里需要注意,因为是在pc端浏览器,是可以随时放大缩小浏览器的,在浏览器大小变化的时候,下载中心的位置是会发生变化的。因此这里需要使用windowresize方式进行监听,随时获取下载中心的位置,并把相关的topleft值进行存储,方便后面调用。

css3相关动画属性

这个动画效果里,主要用到了下边几个属性,简单说一下:

transform:css动画,对应的值可以是二维动画(移动、平面旋转、放大缩小等)、三维动画(x/y/z三维空间动画)

translate3d:包含三个参数,分别为x轴移动距离、y轴移动距离、z轴移动距离。

transition-duration:过渡动画的过渡时间,也就是动画持续的时间。

transition-timing-function:设置过渡动画的动画类型,具体值可以看下图

记录--仿加入购物车飞入动画效果

示例中使用的是transform3d动画,相比普通的二维动画,主要是因为前者可以开启浏览器的gpu硬件加速,能够快速渲染动画。

示例代码

// 小球单独组件 <div class="ball-wrap" v-for="(item, k) of balls" :key="k"   :style="{     opacity: item.show,     top: item.start.y + 'px',     left: item.start.x + 'px',     transitionDuration: (item.show ? (duration/1000) : 0)+'s',     'transition-timing-function': xTimeFunction[!item.ani ? 0 : 1],     transform: 'translate3d(' + item.offset.x + 'px, 0, 0)',     zIndex   }" >   <div class="ball" :class="{ball3d:is3dSheet}"     :style="{       marginLeft: -size/2 + 'px',       marginTop: -size/2 + 'px',       padding: size + 'px',       backgroundImage: ballImage,       backgroundColor: ballColor,       transitionDuration: (item.show ? (duration/1000) : 0) + 's',       transform: 'translate3d(0,' + item.offset.y + 'px,0)',       'transition-timing-function': yTimeFunction[item.ani ? 0 : 1]     }"   ></div> </div>  <script> export default {   props: {     // 球的大小     size: {       type: Number,       default: 8     },     //3D     is3dSheet: {       type: Boolean,       default: true     },     //持续时间     duration: {       type: Number,       default: 800     },     zIndex: {       type: Number,       default: 9999     },     ballImage: {       type: String,       default: ''     },     ballColor: {       type: String,       default: '#409eff'     }   },   data() {     return {       balls: [],       xTimeFunction: ['ease-in', 'ease-out'],  // x轴动画渐入渐出效果       yTimeFunction: ['ease-in', 'ease-out'],  // y轴动画渐入渐出效果       endPos: {         x: sessionStorage.getItem('downIconLeft'),   // 因为浏览器可能会手动放大缩小,所以要监听window的resize时间,获取顶部元素位置         y: sessionStorage.getItem('downIconTop')       }     };   },   mounted() {     this.initBalls()   },   methods: {     // 外部调用方法,传入点击时元素的xy位置数值     drop(pos){       this.endPos.x = sessionStorage.getItem('downIconLeft')       this.endPos.y = sessionStorage.getItem('downIconTop')       let ball        let duration=this.duration       for (var i = 0; i < this.balls.length; i++) {         if(this.balls[i].show){continue}         ball = this.balls[i]       }       ball.start.x = pos.x       ball.start.y = pos.y       ball.offset.x = this.endPos.x - pos.x        ball.offset.y = this.endPos.y - pos.y        if(ball.offset.y > 0){         ball.ani = 1       }else{         ball.ani = 0       }       ball.show = 1                setTimeout(()=>{         ball.show = 0       }, duration)       debounce(this.initBalls,  duration+200, this)()     },          initBalls(){       const balls = [{           show: 0,           start: {             x: 0,             y: 0           },           offset: {             x: 0,             y: 0           },           ani: 0       }]       this.balls = balls     }   } } </script> 

// 下载中心 <span class="export_center_icon" ref="downRef">下载中心</span>  // 获取下载按钮位置 const getIconSite = ()=>{   let downIconSite = downRef?.value?.getBoundingClientRect()   sessionStorage.setItem('downIconLeft', downIconSite.left.toFixed(2))   sessionStorage.setItem('downIconTop', downIconSite.top.toFixed(2)) }  // 监听屏幕变化按钮位置 window.addEventListener('resize', debounce(()=>{   getIconSite() }), 500)  onMounted(()=>{   getIconSite() })  onBeforeUnmount(()=>{   window.removeEventListener('resize') })

// 组件调用 import ball from '@/components/ball/index.vue'   <ball ref="cartBtn"></ball>   <button @click='download($event)'>下载</button>   // 适当方法里调用  download = ()=>{    cartBtn.value.drop({      x: e.clientX,      y: e.clientY    })  }

简单的小球飞入动画就完成了,类似的效果可以用到很多地方,不需要太多逻辑代码,朴实无华效果最靠谱?

本文转载于:

https://juejin.cn/post/7294241942183313447

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录--仿加入购物车飞入动画效果