vue实现购物车抛物线小球动画效果的方法详解


Posted in Javascript onFebruary 13, 2019

本文实例讲述了vue实现购物车抛物线小球动画效果的方法。分享给大家供大家参考,具体如下:

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"></span>
  </div>
  </transition>
  <!--增加商品-->
  <div class="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程序设计有所帮助。

Javascript 相关文章推荐
js设置function参数默认值(适合没有传参情况)
Feb 24 Javascript
js+canvas简单绘制圆圈的方法
Jan 28 Javascript
原生JS实现九宫格抽奖效果
Apr 01 Javascript
JS简单实现点击按钮或文字显示遮罩层的方法
Apr 27 Javascript
浅谈vue+webpack项目调试方法步骤
Sep 11 Javascript
Node.js搭建小程序后台服务
Jan 03 Javascript
Angularjs中date过滤器失效的问题及解决方法
Jul 06 Javascript
jQuery Ajax实现Select多级关联动态绑定数据的实例代码
Oct 26 jQuery
vue-cli3使用 DllPlugin 实现预编译提升构建速度
Apr 24 Javascript
微信小程序如何调用图片接口API并居中显示
Jun 29 Javascript
Angular8基础应用之表单及其验证
Aug 11 Javascript
vue跳转方式(打开新页面)及传参操作示例
Jan 26 Javascript
Jquery实现无缝向上循环滚动列表的特效
Feb 13 #jQuery
vuex实现的简单购物车功能示例
Feb 13 #Javascript
jquery无缝图片轮播组件封装
Nov 25 #jQuery
Vue中多个元素、组件的过渡及列表过渡的方法示例
Feb 13 #Javascript
vue写h5页面的方法总结
Feb 12 #Javascript
如何将百度地图包装成Vue的组件的方法步骤
Feb 12 #Javascript
微信小程序websocket聊天室的实现示例代码
Feb 12 #Javascript
You might like
PHP通用检测函数集合
2011/02/08 PHP
Laravel框架中扩展函数、扩展自定义类的方法
2014/09/04 PHP
php使用Imagick生成图片的方法
2015/07/31 PHP
可缩放Reloaded-一个针对可缩放元素的复用组件
2007/03/10 Javascript
jquery 弹出层实现代码
2009/10/30 Javascript
javascript 利用Image对象实现的埋点(某处的点击数)统计
2012/12/28 Javascript
JS求平均值的小例子
2013/11/29 Javascript
javascript 通用loading动画效果实例代码
2014/01/14 Javascript
jquery通过load获取文件的内容并跳到锚点的方法
2015/01/29 Javascript
javascript实现图片自动和可控的轮播切换特效
2015/04/13 Javascript
javascript文本模板用法实例
2015/07/31 Javascript
基于JavaScript实现通用tab选项卡(通用性强)
2016/01/07 Javascript
jquery ajax分页插件的简单实现
2016/01/27 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单的实现代码
2016/06/23 Javascript
AngularJs ng-route路由详解及实例代码
2016/09/14 Javascript
Bootstrap CSS组件之分页(pagination)和翻页(pager)
2016/12/17 Javascript
Flutter部件内部状态管理小结之实现Vue的v-model功能
2019/06/11 Javascript
ES10的13个新特性示例(小结)
2019/09/23 Javascript
如何利用node.js开发一个生成逐帧动画的小工具
2019/12/01 Javascript
使用 UniApp 实现小程序的微信登录功能
2020/06/09 Javascript
vue双击事件2.0事件监听(点击-双击-鼠标事件)和事件修饰符操作
2020/07/27 Javascript
[40:53]完美世界DOTA2联赛PWL S3 Magma vs DLG 第二场 12.18
2020/12/20 DOTA
解决uWSGI的编码问题详解
2017/03/24 Python
对python中的logger模块全面讲解
2018/04/28 Python
Django项目中用JS实现加载子页面并传值的方法
2018/05/28 Python
将Dataframe数据转化为ndarry数据的方法
2018/06/28 Python
基于tensorflow指定GPU运行及GPU资源分配的几种方式小结
2020/02/03 Python
Python多进程编程multiprocessing代码实例
2020/03/12 Python
pycharm解决关闭flask后依旧可以访问服务的问题
2020/04/03 Python
Python中使用threading.Event协调线程的运行详解
2020/05/02 Python
Html5 页面适配iPhoneX(就是那么简单)
2019/09/05 HTML / CSS
日本最大美瞳直送网:Morecontact(中文)
2019/04/03 全球购物
建筑专业毕业生自荐信
2014/05/25 职场文书
县长群众路线对照检查材料思想汇报
2014/10/02 职场文书
满月酒邀请函
2015/01/30 职场文书
nginx 配置缓存
2022/05/11 Servers