近期对管理后台相关功能进行优化,其中导出功能涉及到查询数据过多导致查询很慢问题,决定采用点击后加入到下载中心方式,既解决了接口慢等待问题,也方便后期各种文件的重复下载,一举多得~
功能上很好实现,调接口就可以了,主要涉及到一个小球飞入效果,基础原理和商城的加入购物车很像,就是点击按钮之后,出现一个小球,按照一定路径飞入固定位置。先来看下基本的原理图:

最终效果就是,点击按钮,出现小球按照红色线路径飞入到下载中心位置。通过原理图,我们也可以看出。只要知道两个元素的位置差,然后通过一定属性控制动画路径就可以了,这里采用了css3的transfrom动画。
两个元素的位置差
获取位置差x轴:下载中心.left - 按钮.clientx
获取位置差y轴:下载中心.top - 按钮.clienty
其中按钮的相关属性,可以在点击时通过$event去获取。
下载中心相关属性,通过ref?.value?.getboundingclientrect()获取。同时这里需要注意,因为是在pc端浏览器,是可以随时放大缩小浏览器的,在浏览器大小变化的时候,下载中心的位置是会发生变化的。因此这里需要使用window的resize方式进行监听,随时获取下载中心的位置,并把相关的top和left值进行存储,方便后面调用。
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
})
}
简单的小球飞入动画就完成了,类似的效果可以用到很多地方,不需要太多逻辑代码,朴实无华效果最靠谱
以上就是javascript模拟实现加入购物车飞入动画效果的详细内容,更多关于javascript购物车飞入动画的资料请关注代码网其它相关文章!
发表评论