来自:https://segmentfault.com/a/1190000009294321 (侵删)

git 源码地址  https://github.com/ustbhuangyi/vue-sell(侵删)

html代码

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

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

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

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

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

 
    <div class="ball-container">
<div v-for="ball in balls">
//用了两种方式的动画,css和js钩子
<transition name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">
//外层动画
<div class="ball" v-show="ball.show">
//内层动画
<div class="inner inner-hook"></div>
</div>
</transition>
</div>
</div>

js代码

  • 设置了balls数组来代表五个小球

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

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

      • 触发了drop事件

      • beforeDrop开始执行

      • dropping开始执行

      • afterDrop开始执行

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

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

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

    • methods: {
      drop(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;
      }
      }
      }, beforeDrop(el){ //这个方法的执行是因为这是一个vue的监听事件
      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); //负数,因为是从左上角往下的的方向
      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)`;
      }
      }
      }, dropping(el, done) { //这个方法的执行是因为这是一个vue的监听事件
      /* 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为了知道过渡的完成,必须设置相应的事件监听器。
      });
      }, afterDrop(el) { //这个方法的执行是因为这是一个vue的监听事件
      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重绘

        • 因为浏览器对于重绘是有要求并且是有队列完成的,这是主要为了性能,虽然动画隐藏了小球display none,但没有触发html重绘,或者说没有立即触发html重绘,所以需要手动

        • let rf = el.offsetHeight; 这是一个手动触发html重绘的方法

        • 网页性能管理详解

        • 高性能JavaScript 重排与重绘

      css代码

    • .ball-container
      .ball
      position: fixed //小球动画必须脱离html布局流
      left: 32px
      bottom: 22px
      z-index: 200
      transition: all 0.4s 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 0.4s linear

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

关于购物车添加按钮的动画(vue.js)的更多相关文章

  1. 添加谷歌拓展程序 vue.js devtools过程中的问题

    在用vue做项目过程中,需要用到vue.js devtools,在从github上面clone下来代码,然后再npm install ,过程报错,然后更新npm包也是会有问题,以下是install的问 ...

  2. 【Vue】转-Vue.js经典开源项目汇总

    版权声明:本文为EnweiTech原创文章,未经博主允许不得转载. https://blog.csdn.net/English0523/article/details/88694219 Vue是什么? ...

  3. vue.js相关UI组件收集

    内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 ###UI组件 element ★9689 - 饿了么出品的Vue2的web UI工具套件 Vux ★6927 - 基于Vu ...

  4. 【前端】Vue.js经典开源项目汇总

    Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) ...

  5. Vue.js经典开源项目汇总

    Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) ...

  6. Vue.js经典开源项目汇总-前端参考资源

    Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) ...

  7. (GoRails )使用Vue.js制作拖拉list功能(v1-4) gem 'acts_as_list'(自动排列顺序)

    系列视频: use Vue.js to build the drag and drop support for the list themselves the cards that are under ...

  8. (私人收藏)Vue.js手册及教程

    (私人收藏)Vue.js手册及教程 https://pan.baidu.com/s/1XG1XdbbdBQm7cyhQKUIrRQ5lrt Vue.js手册及教程 Vue.js 教程 Vue.js 安 ...

  9. vue.js如何实现点击按钮动态添加li

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

随机推荐

  1. [Postman]请求(6)

    您可以从以下位置创建并保存请求: 工作区构建视图 新按钮 启动屏幕 使用新按钮 在标题工具栏中,单击“ 新建”按钮. 出现“新建”屏幕. 在SAVE REQUEST屏幕中: 输入您的请求的标题和说明. ...

  2. Cloud-Platform部署学习

    1. Cloud-Platform部署学习 1.1. 介绍 Cloud-Platform是国内首个基于Spring Cloud微服务化开发平台,核心技术采用Spring Boot2以及Spring C ...

  3. 数字(Number)类型(一)

    多行语句 Python 通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠(\)来实现多行语句,例如: total = item_one + \ item_two + \ item_three ...

  4. 高数复习--什么是DCT

    离散余弦变换(英语:discrete cosine transform, DCT)是与傅里叶变换相关的一种变换,类似于离散傅里叶变换,但是只使用实数.离散余弦变换相当于一个长度大概是它两倍的离散傅里叶 ...

  5. 微信公众平台开发——为何不能在网页调用微信jsapi?

    说到这问题,相信大部分程序员老手都会轻蔑一笑,当然是跨域导致的啊!但是为了一些小白,我觉得还是很有必要再说一次的. 首先介绍什么是跨域,由于浏览器的同源策略,出于防范跨站脚本的攻击,禁止客户端脚本( ...

  6. 【spring boot】idea下springboot打包成jar包和war包,并且可以在外部tomcat下运行访问到(转)

    转自:https://www.cnblogs.com/sxdcgaq8080/p/7727249.html   接着上一章走呗:http://www.cnblogs.com/sxdcgaq8080/p ...

  7. JavaScript中的原型链原理

    工作中经常解除到prototype的概念,一开始错误的认为prototype是对象的原型链,其实prototype只能算是JavaScript开放出来的原型链接口,真正的原型链概念应该是__proto ...

  8. sql server 日志文件结构及误操作数据找回

    一. 概述 在sql server 里有数据文件.mdf和日志文件.ldf,日志文件是sqlserver数据库的另一个重要组成部分,日志文件记录了所有事务以及每个事务对数据库所做的修改.为了提高数据库 ...

  9. Java并发编程之AQS

    一.什么是AQS AQS(AbstractQueuedSynchronize:队列同步器)是用来构建锁或者其他同步组件的基础框架,很多同步类都是在它的基础上实现的,比如常用的ReentrantLock ...

  10. 让Python代码更快运行的 5 种方法

    不论什么语言,我们都需要注意性能优化问题,提高执行效率.选择了脚本语言就要忍受其速度,这句话在某种程度上说明了Python作为脚本语言的不足之处,那就是执行效率和性能不够亮.尽管Python从未如C和 ...