• 生成一个动画小球的div,并且生成五个小球,五个是为了生成一定数量的小球来作为操作使用,按照小球动画的速度,一般来说五个也可以保证有足够的小球数量来运行动画

  • 动画的内容分别是外层和内层,外层控制动画小球的轨道和方向,内层控制动画小球的运行状态

  • 动画使用vue的js钩子实现

  • 因为小球动画只有一个方向(只执行单方向从上到下滚落),所以只用了before-enter,enter,after-enter

  • 用v-show控制小球的可见性,在动画执行期间可见,其余时候隐藏

  • <div class="ball-container">
    <transition name="fade" v-for="ball in balls"
    :key="ball.show"
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter">
    <div class="ball" v-show="ball.show">
    <div class="inner inner-hook"></div>
    </div>
    </transition>
    </div>
    • 设置了balls数组来代表五个小球

    • 设置了dropBalls数组正在运行的小球

data() {
return {
bar: '',
balls: [
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
}
],
dropBalls: []
}
}
      • 只要触发了drop事件,不止是drop事件里面的代码会执行,另外几个vue的js监听钩子也会一起按顺序执行

        • 触发了drop事件

        • beforeEnter开始执行

        • enter开始执行

        • afterEnter开始执行

      • drop事件的触发可以通过点击cartcontrol组件的添加小球按钮addCart事件触发使用$emit,也可以父组件this.$refs.shopcart.drop(target);直接触发

        • 这么做的目的是实现,在子组件cartcontrol点击之后,可以将该dom传给父组件goods然后再传给子组件shopcart,(因为目前他们之间的通道就是这样,shopcart子组件并没有导入cartcontrol子组件,所以没有直接通讯)这样就实现了多个组件之间的通讯,从而可以实现需求,例如这里就是实现点击子组件cartcontrol后添加一个动画,将小球滑落到另外一个组件shopcart

      • $emit是触发当前实例上的事件。附加参数都会传给监听器回调。

methods: {
drop(el) {
console.log('子组件检测到了', el)
for (let i = 0; i < this.balls.length; i++) {
let ball = this.balls[i]
if (!ball.show) { // 将false的小球放到dropBalls
ball.show = true
ball.el = el // 设置小球的el属性为一个dom对象
this.dropBalls.push(ball)
return
}
}
},
beforeEnter(el) { // 这个方法的执行是因为这是一个vue的监听事件
console.log('小球进入以前', el)
let count = this.balls.length
while (count--) {
let ball = this.balls[count]
if (ball.show) {
let rect = ball.el.getBoundingClientRect() // 获取小球的相对于视口的位移(小球高度)
let x = rect.left - 32
let y = -(window.innerHeight - rect.top - 22) // 负数,因为是从左上角往下的的方向
console.log(x, y)
el.style.display = '' // 清空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-hook类来单纯被js操作
inner.style.webkitTransform = `translate3d(${x}px,0,0)`
inner.style.transform = `translate3d(${x}px,0,0)`
}
}
},
enter(el, done) { // 这个方法的执行是因为这是一个vue的监听事件
console.log('小球进入中', el)
/* eslint-disable no-unused-vars */
let rf = el.offsetHeight // 触发重绘html
this.$nextTick(() => { // 让动画效果异步执行,提高性能
el.style.webkitTransform = 'translate3d(0,0,0)'
el.style.transform = 'translate3d(0,0,0)'
// 处理内层动画
let inner = el.getElementsByClassName('inner-hook')[0] // 使用inner-hook类来单纯被js操作
inner.style.webkitTransform = 'translate3d(0,0,0)'
inner.style.transform = 'translate3d(0,0,0)'
el.addEventListener('transitionend', done) // Vue为了知道过渡的完成,必须设置相应的事件监听器。
})
},
afterEnter(el) { // 这个方法的执行是因为这是一个vue的监听事件
console.log('小球进入完成', el)
let ball = this.dropBalls.shift() // 完成一次动画就删除一个dropBalls的小球
if (ball) {
ball.show = false
el.style.display = 'none' // 隐藏小球
}
}
}
  • 关于transitionend

  • 关于drop方法,是实现每一个ball的show属性和el属性处理,并且点击一次会自动将一个小球放到dropBalls数组里面,放到里面就代表的是一个小球已经被开始执行动画,但是由于动画是异步的,所以先主动设置.

  • 关于getBoundingClientRect(位移的计算是从左上角开始)

    • 使用getBoundingClientRect获取到当前元素的坐标,然后需要位移的left减去元素的宽获取真正的最终位移x坐标

    • 使用getBoundingClientRect获取到当前元素的坐标,然后需要当前屏幕的高度减去元素的top再减去元素本身的高度获取到真正的最终位移y坐标,并且这个是负数,因为是从左上角往下的方向

  • 关于html重绘

.ball-container
.ball
position fixed
left: 32px
bottom: 22px
z-index:200
transition: all .6s cubic-bezier(0.49, -0.29, 0.75, 0.41)
.inner
width 16px
height 16px
border-radius 50%
background rgb(0,160,220)
transition: all .6s linear

关于cubic-bezier(0.49, -0.29, 0.75, 0.41),是动画抛物曲线(贝塞尔曲线)的配置,基于css3实现,http://cubic-bezier.com/#.17,.67,.83,.67,参考贝塞尔曲线与CSS3动画、SVG和canvas的基情 ,至于抛物线放在外层就是为了控制内层的元素的轨道和方向的.

原文地址:http://www.cnblogs.com/yuxingyoucan/p/7063881.html

vue.js加入购物车小球动画的更多相关文章

  1. 使用vue模拟购物车小球动画

    使用vue模拟购物车小球动画 1.效果演示 2.相关代码 <!DOCTYPE html> <html lang="en"> <head> < ...

  2. vue.js实现购物车功能

    购物车是电商必备的功能,可以让用户一次性购买多个商品,常见的购物车实现方式有如下几种: 1. 用户更新购物车里的商品后,页面自动刷新. 2. 使用局部刷新功能,服务器端返回整个购物车的页面html 3 ...

  3. Vue.js 相关知识(动画)

    1. 简介 Vue 在插入.更新或移除 DOM 时,提供多种不同方式的过渡效果,并提供 transition 组件来实现动画效果(用 transition 组件将需执行过渡效果的元素包裹) 语法:&l ...

  4. 用vue.js实现购物车功能

    购物车是电商必备的功能,可以让用户一次性购买多个商品,常见的购物车实现方式有如下几种: 1. 用户更新购物车里的商品后,页面自动刷新. 2. 使用局部刷新功能,服务器端返回整个购物车的页面html 3 ...

  5. Vue实现购物车小球动画

    思路: 1.因页面分组件分的比较细,由图可知是组件5到组件4的联动. 如果利用组件间通信需要 子组件5 -->组件3-->所有组件的父组件-->组件4, 层级略显复杂,所以使用了vu ...

  6. vue 2.0 购物车小球抛物线

    备注:此项目模仿 饿了吗.我用的是最新的Vue, 视频上的一些写法已经被废弃了. 布局代码 <div class="ball-container"> <trans ...

  7. vue.js实战——购物车练习(包含全选功能)

    vue.js实战第5章 54页的练习1 直接放代码好了,全选的部分搞了好久,代码好像有点啰嗦,好在实现功能了(*^▽^*) HTML: <!DOCTYPE html> <html l ...

  8. js加入购物车抛物线动画

    天猫将商品加入购物车会有一个抛物线动画,告诉用户操作成功以及购物车的位置,业务中需要用到类似的效果,记录一下实现过程备忘,先上demo 一开始没有想到用抛物线函数去做,也已经忘记还有这么个函数了,想着 ...

  9. css贝塞尔曲线模仿饿了么购物车小球动画

    在线观看贝塞尔曲线值:传送门 在线观看动画效果:传送门 代码: <!DOCTYPE html> <html> <head> <meta charset=&qu ...

随机推荐

  1. Backup Log

    使用Backup Log 命令可进行数据库的事务日志备份.其语法格式如下: Backup 数据库名 To 备份设备 和备份数据库操作一样

  2. Java - 谨慎覆盖equals

    平时很难遇到需要覆盖equals的情况. 什么时候不需要覆盖equals? 类的每个实例本质上是唯一的,我们不需要用特殊的逻辑值来表述,Object提供的equals方法正好是正确的. 超类已经覆盖了 ...

  3. Java 基础(6)——关键字 & 标识符 & 转义字符

    依然是基础的一天,看一看就好~ 关键字 之前就有说过关键字哦~ 注:关键字就是程序发明者规定的有特殊含义的单词. from Java基础(2) Java 中除了关键字以外还有暂时没有成为关键字的保留字 ...

  4. Mybatis执行sql(insert、update、delete)返回值问题

    数据库:Mysql 在使用mybatis的过程中对执行sql的返回值产生疑问,顺手记录一下. 结论: insert:   插入n条记录,返回影响行数n.(n>=1,n为0时实际为插入失败) up ...

  5. js中random的应用

    1.生成一个随机数 var r = Math.random(); console.info(r); 结果生成一个0-1的随机数(返回0和1之间的伪随机数,可能为0,但总是小于1,[0,1)) 2.生成 ...

  6. nginx关于 error_page指令详解.md

    error_page指令解释 nginx指令error_page的作用是当发生错误的时候能够显示一个预定义的uri,比如: error_page 502 503 /50x.html; 这样实际上产生了 ...

  7. 不同浏览器下word-wrap,word-break,white-space强制换行和不换行总结

    强制换行与强制不换行用到的属性 我们一般控制换行所用到的CSS属性一共有三个:word-wrap; word-break; white-space.这三个属性可以说是专为了文字断行而创造出来的.首先我 ...

  8. 你必须知道的get与post的真正区别

    我们会经常看到有人问:http协议中GET请求和POST请求有什么区别~? 这个问题看似很简单,但是不同程度的人会回答出不同的结果.在公司的面试中,也会经常的问及类似这样的问题,看似很简单,但是不同层 ...

  9. SSIS 和 SSRS自制Template

    可以使用VS 制作一个SSIS 的Package. 路径:C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\PrivateAssembl ...

  10. Java数字和字符串的相互转换(BigDecimal的使用)

    String s = "100."; double d1 = "1.23"; double d = Double.parseDouble(s); s = Str ...