uni-app加入购物车动画效果

本文介绍了一个基于Vue的购物车实现方案,通过自定义组件实现了商品加入购物车时的动画效果,并解决了元素抖动的问题。文章详细展示了如何利用Vue的响应式特性结合CSS样式来制作流畅的动画。

index.vue

<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/cart.png" mode="widthFix"></image>
		</view>
		
		<!-- 只需要绑定购物车位置即可 -->
		<flyInCart ref="inCart" :cartBasketRect="cartBasketRect"></flyInCart>
	</view>
</template>

<script>
	//  加入购物车动画组件
	import flyInCart from '@/components/flyInCart.vue'
	
	export default {
		components:{
			flyInCart
		},
		data() {
			return {
				title: 'Hello',
				//购物车位置数据
				cartBasketRect:{},
				//商品数据
				shops:[
					{id:1,img:'../../static/1.jpg',name:'猫的娃娃',price:'666'},
					{id:2,img:'../../static/2.jpg',name:'DVDAV发',price:'5'},
					{id:3,img:'../../static/3.jpg',name:'ad分',price:'5.5'},
					{id:4,img:'../../static/4.jpg',name:'恩爱大V发',price:'44'},
					{id:5,img:'../../static/5.jpg',name:'安防重复',price:'1'},
					{id:6,img:'../../static/5.jpg',name:'安防重复',price:'1'},
					{id:56,img:'../../static/5.jpg',name:'安防重复',price:'1'},
					{id:566,img:'../../static/5.jpg',name:'安防重复',price:'1'},
					{id:5666,img:'../../static/5.jpg',name:'安防重复',price:'1'},
					{id:56666,img:'../../static/5.jpg',name:'安防重复',price:'1'},
					{id:566666,img:'../../static/5.jpg',name:'安防重复',price:'1'},
					{id:5666666,img:'../../static/5.jpg',name:'安防重复',price:'1'}, 
					
				]
			}
		},
		
		methods: {
			//e 是位置等参数  id是为了重复使用点击位置点  需要保证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 => {
				 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: 20px;
		height: 45px;
		background: #1b1919;
		margin: auto;
		border-radius: 20px;
		left: 2%;
	}
	.cart image{
		width: 160rpx;
		position: absolute;
		bottom: 0;
		left: 5%;
	}
</style>

components 下面的文件

 <!--  这个文件夹 插件要求的   跟外面的一模一样,。。。。。。 -->
<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;' : '' "></view>
		</view>
	</view>
</template>
 
<script>
	export default {
		props:{
			cartBasketRect:Object,// 购物车篮的rect信息
		},
		 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: 30rpx;
	height: 30rpx;
	position: fixed;
	border-radius: 50%;
	opacity: 0;
}
</style> 
本课程讲了Vue3+Vue2+Uni-app(uniapp)入门基础与实战,其中还重点讲解了ES6、TypeScript这些基础知识,实战由两大价值5000元的真实企业级项目组成,分别是仿京东电商网站和仿美团微信点餐小程序,同时两大项目代码全部赠送,还赠送前后端架构模板,工作中直接使用。VUE和uni-app是目前热门的前端框架,本课程教你如何快速学会VUE和uni-app并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件和插件,正式上线白屏问题,性能优化、解决iphoneX“刘海”兼容性问题、微信支付、微信授权登录,获取位置在地图上显示,获取用户所在的城市和街道信息,微信小程序发布审核等。对正在工作当中或打算学习VUE和uni-app高薪就业的你来说,那么这门课程便是你手中的葵花宝典。学习技巧:学习当中不要只看,一定要多敲代码,如果碰到某一个知识点不是很明白,不要钻牛角尖,千万不要因为一个点,放弃整个森林,接着往下学,硬着头皮开发项目。只要能亲自开发一个完整的项目,你会发现不明白的地方自然而然就明白了,项目做出来就真正的学会了。此vue和uni-app课程以面试和实战为基础进行讲解,每个知识点都会让你知道在实际项目开发中如何使用,学习后,可以开发大型项目,增强逻辑思维,至少让你拥有3年以上开发经验的实力!代码和ppt均可下载!免费提供《企业级完整实战项目接口文档》,绝对可用
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值