关于购物车添加按钮的动画(vue.js)
来自: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'; //隐藏小球
}
}
}关于drop方法,是实现每一个ball的show属性和el属性处理,并且点击一次会自动将一个小球放到dropBalls数组里面,放到里面就代表的是一个小球已经被开始执行动画,但是由于动画是异步的,所以先主动设置.
关于getBoundingClientRect(位移的计算是从左上角开始)
使用getBoundingClientRect获取到当前元素的坐标,然后需要位移的left减去元素的宽获取真正的最终位移x坐标
使用getBoundingClientRect获取到当前元素的坐标,然后需要当前屏幕的高度减去元素的top再减去元素本身的高度获取到真正的最终位移y坐标,并且这个是负数,因为是从左上角往下的方向
关于html重绘
因为浏览器对于重绘是有要求并且是有队列完成的,这是主要为了性能,虽然动画隐藏了小球
display none
,但没有触发html重绘,或者说没有立即触发html重绘,所以需要手动let rf = el.offsetHeight;
这是一个手动触发html重绘的方法
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)的更多相关文章
- 添加谷歌拓展程序 vue.js devtools过程中的问题
在用vue做项目过程中,需要用到vue.js devtools,在从github上面clone下来代码,然后再npm install ,过程报错,然后更新npm包也是会有问题,以下是install的问 ...
- 【Vue】转-Vue.js经典开源项目汇总
版权声明:本文为EnweiTech原创文章,未经博主允许不得转载. https://blog.csdn.net/English0523/article/details/88694219 Vue是什么? ...
- vue.js相关UI组件收集
内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 ###UI组件 element ★9689 - 饿了么出品的Vue2的web UI工具套件 Vux ★6927 - 基于Vu ...
- 【前端】Vue.js经典开源项目汇总
Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) ...
- Vue.js经典开源项目汇总
Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) ...
- Vue.js经典开源项目汇总-前端参考资源
Vue.js经典开源项目汇总 原文链接:http://www.cnblogs.com/huyong/p/6517949.html Vue是什么? Vue.js(读音 /vjuː/, 类似于 view) ...
- (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 ...
- (私人收藏)Vue.js手册及教程
(私人收藏)Vue.js手册及教程 https://pan.baidu.com/s/1XG1XdbbdBQm7cyhQKUIrRQ5lrt Vue.js手册及教程 Vue.js 教程 Vue.js 安 ...
- vue.js如何实现点击按钮动态添加li
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
随机推荐
- java 堆 栈 方法区的简单分析
Java里的堆(heap)栈(stack)和方法区(method) 基础数据类型直接在栈空间分配, 方法的形式参数,直接在栈空间分配,当方法调用完成后从栈空间回收. 引用数据类型,需要用new来创 ...
- Day10:html和css
Day10:html和css <html> <body> <h1>标题</h1> <p>段落</p> </body> ...
- Netty Decoder:ByteToMessageDecoder
1. ByteToMessageDecoder 这个类是解码器的基类,其中描述了解码器基本的工作方式和实现原理::还定义了一个解码的抽象方法decode,这个方法由业务实现,负责将一段字节数据解码为具 ...
- Dash by Plotly 学习笔记
一.介绍 1.dash 是什么 dash 是一个基于 Flask (Python) + React 的 web 框架. 入门指南:https://dash.plot.ly/getting-starte ...
- alibaba的FastJson找不到JSON对象问题
在现在出现使用JSON.toJsonString()方法时,可能没有JSON这个对象. 这种问题可能是下载的jar版本比较高.在低版本的jar使用的是JSON对象. 我使用的是1.2.47版本的jar ...
- ubuntu16.04 下鼠标变成十字形状无法点击情况解决
出现这种问题的原因是把shell命令行终端当成了python环境,误输入了"import"命令. (当然如果你真的希望在shell中输入import指令除外...) 我自己想当然的 ...
- linux查看系统32位还是64位
1. 从系统查看 1.1 uname -a 命令 [root@qs-dmm-rh2 ~]# uname -a Linux qs-dmm-rh2 2.6.18-194.el5 #1 SMP Tue Ma ...
- json模块及其API
模块:json 所包含API列表: json.dumps : 将python对象转换成json格式 json.loads : 将json格式字符串转换为python对象 ——————————————— ...
- 阿里云申请ssl证书
申请证书(本文以阿里云服务器为背景,申请证书也以阿里云域名申请证书来作为实例) (1)登陆阿里云服务器,初次配置的用户,不建议直接搜索‘ssl证书’进行购买,因为这样购买后证书与域名对应的引导性并不强 ...
- 使用SAX解析xml文档
1.首先,在main方法中解析xml文档,具体代码如下: import org.w3c.dom.*; import javax.xml.parsers.DocumentBuilder; import ...