本文实例讲述了vue实现购物车抛物线小球动画效果的方法。分享给大家供大家参考,具体如下:
先上最终效果图,在商品页面和商品详情页面点击加号添加商品时都可以看到小球抛物线落入购物车的动画效果
此文章只写了商品页面购物小球的实现,商品详情页原理类似
实现步骤:
1. 需要三个组件,最下方包含蓝色购物车的【购物车】组件shopCart.vue(子组件),每个【加减号】组成的购物小球组件cartControl.vue(子组件),和包含每个商品信息的goods组件goods.vue(父组件)
2. 原理,购物小球组件在点击加号的时候对外触发事件,将小球对象本身传递给父组件goods组件,再由goods作为桥梁将这个信息传递给另一个子组件shopCart组件,shopCart组件获取到小球对象后,对该小球进行位置计算,从而实现从不同商品的位置添加商品的抛物线小球效果
3. cartControl.vue部分代码
html代码
<div class="cartControl"> <transition name="move"> <!--减少商品--> <div class="decrease " v-show="food.count>0" @click.stop.prevent="decreaseCart"> <span class="inner iconfont">"count" v-show="food.count>0">{{food.count}}</div> <!--点击加号按钮,触发事件addCart,将事件对象作为参数传递--> <div class="add iconfont" @click.stop.prevent="addCart($event)"></div> </div>
js代码
// addCart事件 addCart (event) { if (!event._constructed) return // 检测事件派发是否来自于better-scroll if (!this.food.count) { // 当给一个观测对象添加一个它不存在的属性的时候,直接赋值是不可以的,需要使用Vue.set设置这个属性 Vue.set(this.food, 'count', 1) } else { this.food.count++ } this.$emit('cart-add', event.target) // 向父组件触发一个自定义的cart-add事件,同时将事件对象传递给父组件 },
4. goods.vue部分代码
html代码
<!--加减商品--> <div class="cartControl-wrapper"> <!--在父组件监听到子组件触发的cart-add事件--> <cart-control :food="food" @cart-add="handlecartAdd"></cart-control> </div>
js代码 知识点:子组件和父组件之间的数据传递
_drop (target) { // 在goods.vue定义 _drop方法将cartcontrol的传递过来target对象再传递给shopCart this.$nextTick(() => { // 使用$nextTick优化体验 this.$refs.shopCart.drop(target) // 父组件goods通过.$refs属性访问shopCart子组件的drop方法 }) }, handlecartAdd (target) { // 点击加号按钮触发事件 this._drop(target) // 调用_drop方法 }
5. shopCart.vue部分代码
①.定义一个数组,存放5个小球,这5个小球可以满足的动画的运行
②.动画分为两层,外层控制小球y轴方向和运动的轨道,内层控制x轴方向的运动
③.使用js动画钩子,vue在实现动画的时候提供了几个javascript钩子,可配合css动画一起使用,也可单独使用,因为购物车抛物线小球只有进入动画,没有离开的动画,所以enter的钩子有,before-enter,enter,after-enter,这些钩子需要在html属性中声明,然后在methods中使用这些方法
可参考以下官网
https://cn.vuejs.org/v2/guide/transitions.html#JavaScript-%E9%92%A9%E5%AD%90
④.v-show控制盒子的显示和隐藏
html
<!--购物车小球--> <div class="ball-container"> <div v-for="(ball,index) of balls" :key="index"> <transition @before-enter="handleBeforeEnter" @enter="handleEnter" @after-enter="handleAfterEnter"> <div class="ball" v-show="ball.show" v-bind:css="false"><!--外层盒子--> <div class="inner inner-hook"></div> <!--内层盒子--> </div> </transition> </div> </div>
data
data () { return { // 使用balls存放5个小球,这些小球的默认状态都是不显示的 balls: [{show: false}, {show: false}, {show: false}, {show: false}, {show: false}], dropBalls: [] // 用dropBalls来存放掉落的小球 } }
在methods中定义方法
// 当触发drop方法时小球开始掉落 drop (el) { for (let i = 0; i < this.balls.length; i++) { // 遍历这5个小球 let ball = this.balls[i] if (!ball.show) { // 当小球显示状态为隐藏时 ball.show = true // 将这个小球的显示状态设置为true ball.el = el // 将cartControl传过来的对象挂载到ball的el属性上 this.dropBalls.push(ball) // 将这个小球放入到dropBalls数组中 return } } }
js动画
// js动画钩子 // beforeenter handleBeforeEnter: function (el) { let count = this.balls.length while (count--) { let ball = this.balls[count] if (ball.show) { let rect = ball.el.getBoundingClientRect() // getBoundingClientRect()获取小球相对于视窗的位置,屏幕左上角坐标为0,0 let x = rect.left - 32 // 小球x方向位移= 小球距离屏幕左侧的距离-外层盒子距离水平的距离 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 handleEnter: function (el, done) { /* eslint-disable no-unused-vars */ // 触发浏览器重绘 let rf = el.offsetHeight 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)' el.addEventListener('transitionend', done) // Vue为了知道过渡的完成,必须设置相应的事件监听器。它可以是transitionend或 animationend }) }, handleAfterEnter: function (el) { let ball = this.dropBalls.shift() // 完成一次动画就删除一个dropBalls的小球 if (ball) { ball.show = false el.style.display = 'none' } },
希望本文所述对大家vue.js程序设计有所帮助。
vue,购物车,抛物线,动画
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新动态
- 黑鸭子2010-再度重相逢[首版][WAV+CUE]
- 【原神手游】5.2版本圣遗物优化详情
- 方季惟.1989-一生只爱一次【蓝与白】【WAV+CUE】
- 群星.1997-强力舞曲总动员【金点】【WAV+CUE】
- 盘尼西林.2024-岛与黎明【智慧大狗】【FLAC分轨】
- 刀郎《柔情经典》 2CD[WAV分轨][3.8G]
- 群星2024《民谣精选》原音母版1:1直刻[低速原抓WAV+CUE][1.1G]
- 经典《泰坦尼克号原声大碟》[WAV+DSF+FLAC多版][5.2G]
- 魔兽世界兽王猎输出宏代码是什么 兽王猎翻页输出宏命令代码分享
- 魔兽世界wlk野德一键输出宏是什么 wlk野德一键输出宏介绍
- wlk鸟德一键输出宏是什么 wlk鸟德一键输出宏介绍
- 《明末:渊虚之羽》外网新宣传:有勇气面对障碍吗?
- 视觉盛宴!V社公布《看火人》团队新作水面物理效果演示
- 张艺谋呼吁观众走进影院看电影:对解说短视频很无语
- 车载音乐最强享受 《车载极致女声精选》[WAV分轨][1G]