html代码
- 生成一个动画小球的div,并且生成五个小球,五个是为了生成一定数量的小球来作为操作使用,按照小球动画的速度,一般来说五个也可以保证有足够的小球数量来运行动画
- 动画的内容分别是外层和内层,外层控制动画小球的轨道和方向,内层控制动画小球的运行状态
- 动画使用vue的js钩子实现
- 因为小球动画只有一个方向(只执行单方向从上到下滚落),所以只用了before-enter,enter,after-enter
- 用v-show控制小球的可见性,在动画执行期间可见,其余时候隐藏
1 | <div class="ball-container"> |
js代码
- 设置了balls数组来代表五个小球
- 设置了dropBalls数组正在运行的小球
1 | data(){ |
- 只要触发了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是触发当前实例上的事件。附加参数都会传给监听器回调。
1 | methods: { |
- 关于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代码
1 | .ball-container |
关于cubic-bezier(0.49, -0.29, 0.75, 0.41),是动画抛物曲线(贝塞尔曲线)的配置,基于css3实现,http://cubic-bezier.com/#.17,.67,.83,.67,参考贝塞尔曲线与CSS3动画、SVG和canvas的基情 ,至于抛物线放在外层就是为了控制内层的元素的轨道和方向的.