购物车点击添加按钮实现抛物线飞入效果(贝塞尔曲线)

组件部分,复制使用:

<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>

项目结构:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值