找了很多个加入购物车动画都不行,看到了这个博主的可以,太赞了Uniapp实现加入购物车抛物线效果_uniapp 加入购物车抛物线动画-CSDN博客
因为我的功能和这位博主的不太一样,我的是点击加入购物车获取图片的位置而不是点击的位置,在这个基础上又以一样的方法获取了购物车的位置,做了下小修改,这样应该就不会有兼容问题了。
先上图:
加入过程:点击加入购物车,图片形成一个小球沿着轨迹(类似划线轨迹/抛物线)掉入购物车
界面:
<template>
<view>
<view v-for="(item,index) in itemList" class="flex position-relative"
style="padding: 10rpx 0;border: 1rpx solid #CCCCCC;">
<image class="img" :src="item.image" style="width: 160rpx;height: 160rpx;"></image>
<view class="ml-30u">
<view class="font-weight">{{item.title}}</view>
<view class="">{{item.desc}}!</view>
</view>
<view @click="addShoppingCard(item,index)" class="position-absolute"
style="padding: 10rpx 20rpx;border-radius: 50rpx;background-color: #d995d7;bottom: 20rpx;right: 30rpx;">
加入购物车
</view>
</view>
<!-- 购物车 -->
<view class="cart" :class="shoppingCartAnimation? 'shoppingCartAnimations' : '' ">
<block class="position-relative">
<image src="../../static/cart.png" mode="" class="width-height-50 mt-10u"></image>
<view class="badge">{{info}}</view>
</block>
</view>
<!-- 小球动画 -->
<view :animation="animationY" :style="'position:fixed;top:' + ballY + 'px;'" v-if="showBall">
<view class="ball" :animation="animationX" :style="'position:fixed;left:' + ballX + 'px;'">
<image class="ball" :src="addImg" mode=""></image>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
itemList: [{
title: '喵喵',
desc: '可爱',
image: '../../static/cat.jpg'
}, {
title: '咕噜',
desc: '调皮',
image: '../../static/cat2.png'
}, {
title: '猫猫',
desc: '我的猫猫世界第一可爱',
image: '../../static/cat3.jpg'
}, {
title: '喵喵',
desc: '我的喵喵世界第一可爱',
image: '../../static/cat.jpg'
}, {
title: '喵喵',
desc: '我的喵喵世界第一可爱',
image: '../../static/cat.jpg'
}],
imgListSum: [{
showDel: false,
delAnimation: false, // 删除动画
sum: 0,
}],
shoppingCartAnimation: false, // 购物车动画
showBall: false, // 小球是否显示
animationY: '', // 动画Y
animationX: '', // 动画X
ballY: '', // 小球当前位置Y
ballX: '', // 小球当前位置X
cartX: null, //购物车位置X
cartY: null, //购物车位置Y
info: 0,
addImg: ''
}
},
onShow() {
this.itemList.forEach(item => {
let imgListSum = {
showDel: false,
delAnimation: false, // 删除动画
sum: 0,
}
this.imgListSum.push(imgListSum)
})
this.$nextTick(() => {
// 获取购物车位置
const query = uni.createSelectorQuery().in(this);
query.select('.cart').boundingClientRect(data => {
console.log(data, 'data');
this.cartX = data.left + 20
this.cartY = data.top + 50
console.log(this.cartX, this.cartY, '获取购物车位置');
}).exec();
})
},
methods: {
// 删除购物车
async delShoppingCard(index) {
if (this.imgListSum[index].sum - 1 <= 0) {
this.imgListSum[index].sum = this.imgListSum[index].sum - 1
this.imgListSum[index].delAnimation = false
this.setDelayTime(100).then(() => {
this.imgListSum[index].showDel = false
})
} else {
this.imgListSum[index].sum = this.imgListSum[index].sum - 1
}
},
// 添加购物车
addShoppingCard(item, ind) {
this.addImg = item.image
this.info++
let imgX, imgY;
this.$nextTick(function() {
const query = uni.createSelectorQuery().in(this);
query.selectAll('.img').boundingClientRect(data => {
console.log(data, 'data');
imgX = data[ind].left + 50
imgY = data[ind].top + 50
console.log(imgX, imgY, 'addCardAnimation');
this.imgListSum[ind].sum = this.imgListSum[ind].sum + 1
this.imgListSum[ind].delAnimation = true
this.imgListSum[ind].showDel = true
// x, y表示手指点击横纵坐标, 即小球的起始坐标
let ballX = imgX,
ballY = imgY
this.createAnimation(ballX, ballY);
}).exec();
})
},
// 延迟执行
setDelayTime(sec) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, sec)
});
},
// 创建动画
createAnimation(ballX, ballY) {
uni.getSystemInfo({
success: async (e) => {
// var bottomX = e.windowWidth; // 结束位置X
// var bottomX = 50; // 结束位置X
// var bottomY = e.windowHeight - 50; // 结束位置Y
var bottomX = this.cartX; // 结束位置X
var bottomY = this.cartY; // 结束位置Y
var animationX = this.flyX(bottomX, ballX); // 创建小球水平动画
var animationY = this.flyY(bottomY, ballY); // 创建小球垂直动画
this.ballX = ballX; // 小球当前位置X
this.ballY = ballY; // 小球当前位置Y
this.showBall = true; // 显示小球
this.setDelayTime(100).then(() => {
this.animationX = animationX.export(); // 执行动画X
this.animationY = animationY.export(); // 执行动画Y
// 400ms延时, 即小球的抛物线时长
return this.setDelayTime(400);
}).then(() => {
this.animationX = this.flyX(0, 0, 0).export(); // 执行动画X
this.animationY = this.flyY(0, 0, 0).export(); // 执行动画Y
this.showBall = false; // 隐藏小球
this.shoppingCartAnimation = true // 购物车动画
// 400ms延时, 即小球的抛物线时长
return this.setDelayTime(700);
}).then(() => {
this.shoppingCartAnimation = false // 购物车动画
})
}
})
},
// 水平动画
flyX(bottomX, ballX, duration) {
/**
* bottomX 结束位置
* ballX 开始位置
* duration 动画持续时间
*/
let animation = uni.createAnimation({
duration: duration || 400,
timingFunction: 'linear',
})
animation.translateX(bottomX - ballX).step(); // 动画效果
return animation;
},
// 垂直动画
flyY(bottomY, ballY, duration) {
/**
* bottomY 结束位置
* ballY 开始位置
* duration 动画持续时间
*/
let animation = uni.createAnimation({
duration: duration || 400,
timingFunction: 'ease-in',
})
console.log(bottomY)
animation.translateY(bottomY - ballY).step(); // 动画效果
return animation;
},
}
}
</script>
下面样式有购物车抖动动画哦哈哈哈
<style>
@import url("../../commons/common.css");
.cart {
position: fixed;
right: 50rpx;
bottom: 250rpx;
width: 70rpx;
height: 70rpx;
background-color: #fff;
border: 1rpx solid #ebebeb;
border-radius: 50%;
text-align: center;
}
.badge {
padding: 0 8rpx;
font-size: 18rpx;
border: .4rpx solid #DE1A1B;
color: #DE1A1B;
border-radius: 15rpx;
position: absolute;
top: -10rpx;
right: -18rpx;
background-color: #fff;
}
.flex {
display: flex;
}
.ball {
height: 40rpx;
width: 40rpx;
border-radius: 50rpx;
position: fixed;
}
/* 下面都是购物车抖动 */
.shoppingCartAnimations {
animation: shoppingCartAnimation 1s;
}
@keyframes shoppingCartAnimation {
0% {
opacity: 0;
transform: scale3d(.3, .3, .3)
}
20% {
transform: scale3d(1.1, 1.1, 1.1)
}
40% {
transform: scale3d(.9, .9, .9)
}
60% {
opacity: 1;
transform: scale3d(1.03, 1.03, 1.03)
}
80% {
transform: scale3d(.97, .97, .97)
}
to {
opacity: 1;
transform: scaleX(1)
}
}
/* 从右到左 */
.delRightShoppingCardAnimations {
animation: delRightShoppingCardAnimation .5s;
}
@keyframes delRightShoppingCardAnimation {
from {
transform: translateX(100rpx) rotate(900deg);
animation-timing-function: linear;
}
to {
transform: translateX(0rpx) rotate(0);
}
}
/* 从左到右 */
.delLeftShoppingCardAnimations {
animation: delLeftShoppingCardAnimation .5s;
}
@keyframes delLeftShoppingCardAnimation {
from {
transform: translateX(0rpx) rotate(0);
}
to {
transform: translateX(100rpx) rotate(900deg);
animation-timing-function: linear;
}
}
</style>