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 相关文章推荐
在b/s开发中经常用到的javaScript技术
Aug 23 Javascript
超级酷和最实用的jQuery实例收集(20个)
Apr 21 Javascript
js判断输入是否为正整数、浮点数等数字的函数代码
Nov 17 Javascript
js实现精美的图片跟随鼠标效果实例
May 16 Javascript
CSS javascript 结合实现悬浮固定菜单效果
Aug 23 Javascript
第一次接触JS require.js模块化工具
Apr 17 Javascript
基于Three.js插件制作360度全景图
Nov 29 Javascript
footer定位页面底部(代码分享)
Mar 07 Javascript
vue+webpack模拟后台数据的示例代码
Jul 26 Javascript
js中apply()和call()的区别与用法实例分析
Aug 14 Javascript
Vue+Express实现登录注销功能的实例代码
May 05 Javascript
Flexible.js可伸缩布局实现方法详解
Nov 13 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实现框架(二)
2006/10/09 PHP
探讨php中防止SQL注入最好的方法是什么
2013/06/10 PHP
PHP strstr 函数判断字符串是否否存在的实例代码
2013/09/28 PHP
用PHP解决的一个栈的面试题
2014/07/02 PHP
PHP基于反射机制实现插件的可插拔设计详解
2016/11/10 PHP
PHP 实现浏览记录并按日期分组
2017/05/11 PHP
PHP字典树(Trie树)定义与实现方法示例
2017/10/09 PHP
PHP实现与java 通信的插件使用教程
2019/08/11 PHP
同时使用n个window onload加载实例介绍
2013/04/25 Javascript
js取整数、取余数的方法
2014/05/11 Javascript
Javascript中的方法链(Method Chaining)介绍
2015/03/15 Javascript
Adapter适配器模式在JavaScript设计模式编程中的运用分析
2016/05/18 Javascript
详解Javascript中prototype属性(推荐)
2016/09/03 Javascript
nodeJs内存泄漏问题详解
2016/09/05 NodeJs
Bootstrap 网站实例之单页营销网站
2016/10/20 Javascript
js读取本地文件的实例
2017/12/22 Javascript
vue2.0 如何在hash模式下实现微信分享
2019/01/22 Javascript
小程序调用微信支付的方法
2019/09/26 Javascript
jQuery实现form表单基于ajax无刷新提交方法实例代码
2019/11/04 jQuery
nginx部署多个vue项目的方法示例
2020/09/06 Javascript
在vue中实现清除echarts上次保留的数据(亲测有效)
2020/09/09 Javascript
跟老齐学Python之折腾一下目录
2014/10/24 Python
Python实现的将文件每一列写入列表功能示例【测试可用】
2018/03/19 Python
windows下numpy下载与安装图文教程
2019/04/02 Python
Python3 合并二叉树的实现
2019/09/30 Python
Django 设置admin后台表和App(应用)为中文名的操作方法
2020/05/10 Python
Python eval函数介绍及用法
2020/11/09 Python
可以在一个PHP文件里面include另外一个PHP文件两次吗
2015/05/22 面试题
培训演讲稿范文
2014/01/12 职场文书
幼儿教师研修感言
2014/02/12 职场文书
小学数学教研活动总结
2014/07/01 职场文书
驾驶员安全责任书
2014/07/22 职场文书
邀请书格式范文
2015/02/02 职场文书
教师节感想
2015/08/11 职场文书
Python if else条件语句形式详解
2022/03/24 Python
《勇者辞职不干了》ED主题曲无字幕动画MV公开
2022/04/13 日漫