组件部分,复制使用:
<template>
<view class="relative">
<view class="ball" v-for="(d,i) in balls" :key="i"
:style=" d.inited ? 'transition: transform .5s ease-in; transform: translate3d(0, ' + offsetY + 'px,0); top: ' + ballY + 'px;' : '' ">
<view class="inner arbg" :style="d.inited ? 'transition: transform .5s linear; transform: translate3d( ' + offsetX + 'px,0,0); left: ' + ballX + 'px; opacity: 1;' : '' ">
<image class="addIconimg" src="../../../static/1111.png" mode="heightFix"></image>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
cartBasketRect: Object, // 接收购物车的DOM信息
},
data() {
return {
offsetX: 0,
offsetY: 0,
ballX: 0,
ballY: 0,
balls: {},
//避免抖动
lastEvent: '',
lastId: ''
}
},
created() {
let balls = [];
for (let i = 0; i < 5; i++) {
balls.push({
inited: false
});
}
this.balls = balls
},
methods: {
getBalls() {
return balls;
},
addToCart(e, id) {
if (!id) {
this.lastId = ''
return
}
const self = this
if (this.lastId == id) {
e = this.lastEvent
} else {
this.lastId = id
this.lastEvent = e
}
let ballX = e.touches[0].clientX - 10
let ballY = e.touches[0].clientY - 9;
this.offsetX = -Math.abs(this.cartBasketRect.left - ballX + 10)
this.offsetY = Math.abs(this.cartBasketRect.top - ballY + (this.cartBasketRect.height / 1.5))
this.ballX = ballX
this.ballY = ballY
for (let i = 0; i < 5; i++) {
if (!this.balls[i].inited) {
this.balls[i].inited = true
setTimeout(() => {
self.balls[i].inited = false
}, 500);
break;
}
}
}
}
}
</script>
<style scoped>
.ball {
position: fixed;
z-index: 8;
}
.ball .inner {
background: #ff9900;
width: 40rpx;
height: 40rpx;
position: fixed;
border-radius: 50%;
opacity: 0;
}
.addIconimg{
width: 40rpx;
height: 40rpx;
}
</style>
使用:
<template>
<view class="content">
<view class="list">
<view class="item flex" v-for="(d,i) in shops" :key="i">
<view class="il flexs">
<image :src="d.img" mode="widthFix"></image>
<view class="">
<view class="bold name">{{d.name}}</view>
<view class="price">¥{{d.price}}</view>
</view>
</view>
<!-- id避免抖动 -->
<view class="add flexc bold" @tap="add($event,d.id)">+</view>
</view>
</view>
<view class="cart">
<image id="cart" src="../../static/1111.png" mode="widthFix"></image>
</view>
<!--绑定购物车位置 -->
<flyInCart ref="inCart" :cartBasketRect="cartBasketRect"></flyInCart>
</view>
</template>
<script>
import flyInCart from '../index/components/bezier.vue'
export default {
components: {
flyInCart
},
data() {
return {
title: 'Hello',
//购物车位置数据
cartBasketRect: {},
shops: [{
id: 1,
img: '../../static/1111.png',
name: '商品1',
price: '78'
},
{
id: 2,
img: '../../static/22222.jpg',
name: '商品2',
price: '46'
},
{
id: 3,
img: '../../static/1111.png',
name: '商品3',
price: '23'
},
{
id: 4,
img: '../../static/logo.png',
name: '商品4',
price: '66'
},
{
id: 5,
img: '../../static/1111.png',
name: '商品5',
price: '5'
},
{
id: 6,
img: '../../static/22222.jpg',
name: '商品6',
price: '9'
},
{
id: 7,
img: '../../static/kaihuiskip.jpg',
name: '商品7',
price: '1'
},
{
id: 8,
img: '../../static/22222.jpg',
name: '商品8',
price: '1'
},
{
id: 9,
img: '../../static/logo.png',
name: '商品9',
price: '4'
},
]
}
},
methods: {
//e 是位置等参数,id是为了重复使用点击位置点,需要保证id不重复
add(e, id) {
this.$refs.inCart.addToCart(e, id);
}
},
onPageScroll() {
//重复使用了点击动画位置,保证不抖动,不传参调用即清空点击点
this.$refs.inCart.addToCart();
},
onReady() {
const self = this
let q = uni.createSelectorQuery()
//获取购物车位置
setTimeout(function() {
q.select('#cart').boundingClientRect(data => {
console.log(data);
self.cartBasketRect = data
}).exec();
}, 100)
}
}
</script>
<style>
.list {
padding-top: 50rpx;
}
.price {
font-size: 30rpx;
color: red;
}
.name {
margin-bottom: 70rpx;
}
.flexs {
display: flex;
align-items: flex-start;
}
.flexc {
display: flex;
align-content: center;
justify-content: center;
}
.add {
background: #ff9900;
width: 50rpx;
height: 50rpx;
border-radius: 45%;
position: absolute;
right: 0;
transition: all .13s;
}
.add:active {
transform: scale(1.2);
}
.flex {
display: flex;
align-content: center;
}
.il {}
.il image {
width: 160rpx;
border-radius: 16rpx;
margin-right: 20rpx;
}
.item {
width: 90%;
margin: 50rpx auto;
position: relative;
}
.flex {
display: flex;
align-items: center;
}
.bold {
font-weight: bold;
font-size: 30rpx;
}
.cart {
width: 96%;
position: fixed;
bottom: 70px;
height: 45px;
background: #c3b5b5;
margin: auto;
border-radius: 20px;
left: 2%;
}
.cart image {
width: 80rpx;
position: absolute;
bottom: 0;
left: 5%;
}
</style>
项目结构: