vue饿了么(五)--购物车小球动画实现

1.cartcontrol.vue,添加商品时,派发一个事件给goods.vue,获取当前DOM,方便计算小球下落位置。

addCart(event) {
				if(!event._constructed) {//非自定义点击事件的情况下return掉,这样pc端就不会检测到两次点击事件。
					return;
				}
				// console.log(this.food.count);
				if(!this.food.count){
					Vue.set(this.food,'count',1);
				//给对象添加他不存在的属性时,这样的方式是不行的。需要用Vue的Vue.set()
					// this.food.count=1;
				}else{
					this.food.count++;
				}
				this.$emit('cart-add',event.target);//添加商品时,派发一个事件,将当前DOM传递给goods.vue
			},

2.goods.vue接收

<div class="cartcontrol-wrapper">
    <cartcontrol :food='food' @cart-add="cartAdd"></cartcontrol>
</div>
cartAdd(el) {
    //体验优化,异步执行下落动画,画面不容易卡顿。
	this.$nextTick(() => {
		this.$refs.shopcart.drop(el);
	});
},

3.goods.vue中调用子组件shopcart.vue的drop()方法

drop(el) {
    // console.log(el);
    //遍历小球,找到show为false的小球
    for(let i=0;i<this.balls.length;i++){
	    let ball = this.balls[i];
	    if(!ball.show) {
		    ball.show = true;
		    ball.el = el;//用小球的el对象保留这个element
		    this.dropBalls.push(ball);
		    return;
		}
	}
},
<div class="ball-container"> 
	<transition-group name="drop" v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter">
	    <div class="ball" v-for="(ball,index) in balls" v-show="ball.show" :key="index">
			<div class="inner inner-hook"></div>
		</div>
	</transition-group>
</div>

钩子函数

beforeEnter: function (el) {
    /*el是小球;
	遍历所有show为true的小球*/
	let count = this.balls.length;
	while(count--) {
		let ball = this.balls[count];
		if(ball.show) {
			let rect = ball.el.getBoundingClientRect();//获得该元素(加号)相对于视口的位置的偏移(left,top)
			let x = rect.left-32;
			let y = -(window.innerHeight-rect.top-22);
			el.style.display = '';
			el.style.webkitTransform = `translate3d(0,${y}px,0)`;//外层做纵向运动
			el.style.transform = `translate3d(0,${y}px,0)`;
			let inner = el.getElementsByClassName('inner-hook')[0];
			inner.style.webkitTransform = `translate3d(${x}px,0,0)`;
			inner.style.transform = `translate3d(${x}px,0,0)`;
		}
	}
},
enter: function (el) {
	let rf = el.offsetHeight;//必须重绘,再进行transform才有用
	this.$nextTick(() => {
	    el.style.webkitTransform = 'translate3d(0,0,0)';//外层做纵向运动
		el.style.transform = 'translate3d(0,0,0)';
		let inner = el.getElementsByClassName('inner-hook')[0];
		inner.style.webkitTransform = 'translate3d(0,0,0)';
		inner.style.transform = 'translate3d(0,0,0)';
	});
},
afterEnter: function (el) {
	let ball = this.dropBalls.shift();
	if(ball) {
		ball.show = false;
	    el.style.display = 'none';
	}
}
.ball-container {
    .ball {
		position: fixed;
		left: 32px;
		bottom: 22px;
		width: 16px;
		heigth: 16px;
		z-index: 200;
		.inner {
			width: 16px;
			height: 16px;
			border-radius: 50%;
			background: rgb(0,160,220);
		}
		&.drop-enter-active,&.drop-leave-active {
			transition: all 0.4s cubic-bezier(0.49,-0.29,0.75,0.41);
			.inner {
				transition: all 0.4s linear;
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42424660/article/details/83751622