# 小球飞入购物车
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Swiper demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1">
<link rel="stylesheet" href="http://at.alicdn.com/t/font_695306_0fo55mcu0auk.css">
<style>
*{margin: 0;padding:0}
#app{
position: relative;
margin: 0 auto;
width: 375px;
height:667px;
background:#AEDEFC
}
#app .ball{
width: 20px;
height: 20px;
position:absolute;
right:15px;
top:80px;
z-index:200;
}
/* 一排小球 */
#app .ball .inner{
position: absolute;
top: 0;
width:16px;
height:16px;
border-radius:50%;
/* background-color:rgb(0,160,220); */
background: #FB929E;
}
/* 购物车 */
#app .box{
position: absolute;
bottom: 20px;
left: 40px;
width:60px;
height:60px;
font-size: 60px;
color: #FB929E;
transform: translateX(-20px);
}
button{
position: absolute;
z-index: 10;
width: 20px;
height: 20px;
border-radius: 50%;
background-color:rgb(0,160,220);
text-align: center;
color:#fff;
padding: 0;
border:none;
outline: none;
cursor:pointer
}
.show{
opacity: 0;
}
</style>
</head>
<body>
<div id="app">
<!-- 按钮和小球球的位置的wrap -->
<div class="ball">
<button @click="addCart">+</button>
<div v-for="ball in balls"
:class="{show: !ball.run}"
class="inner" ref="ball">
</div>
</div>
<i class="box iconfont icon-shangpinguanli" ref="cart"></i>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
balls: [
{run: false},
{run: false},
{run: false},
{run: false},
{run: false},
{run: false},
{run: false}
],
ballIndex: 0
},
watch: {
// 超过数量归零
ballIndex(nv) {
console.log(nv)
this.ballIndex = nv == this.balls.length ? 0 : nv;
}
},
methods: {
parabola(element, options, arc, duration){
duration = duration || 800;
//小球的初始坐标 - 购物车初始坐标
var start = this.offset(element);
var x = options.left - start.left,
y = options.top - start.top;
var a = arc, c = 0, b = (y - a * x * x) / x;
//毫秒数
var date = +new Date();
var timer = setInterval(() => {
var elapsed = Math.min(+new Date() - date, duration);
var _x = elapsed * x / duration,
_y = a * _x * _x + b * _x + c;
this.offset(element, {left : _x + start.left, top : _y + start.top});
if(elapsed === duration)
clearInterval(timer);
},1000/50)
},
offset(element,coord){
if(typeof coord === "undefined"){
var _top = 0, _left = 0;
while(element !== null){
_top += element.offsetTop;
_left += element.offsetLeft;
element = element.offsetParent;
}
return {top : _top, left : _left};
}
var _top = 0, _left = 0, parent = element.offsetParent;
while(parent !== null){
_top += parent.offsetTop;
_left += parent.offsetLeft;
parent = parent.offsetParent;
}
_left = coord.left - _left;
/*要设置的相对文档的定位距离相当于是用此距离减去其父元素在文档中的定位*/
_top = coord.top - _top;
// css(element,{left : _left+"px", top : _top+"px"});
element.style.left = _left+"px";
element.style.top = _top+"px";
},
// 点击购物车,选中第几个小球,调用抛物线函数
addCart() {
var idx = this.ballIndex;
this.balls[idx].run = true;
//调用抛物线函数 第几个小球 偏移量 弧度 时间
this.parabola(this.$refs.ball[idx], this.offset(this.$refs.cart), 0.01, 800);
setTimeout(() => {
this.balls[idx].run = false;
this.$refs.ball[idx].style.top = "";
this.$refs.ball[idx].style.left = "";
}, 850);
this.ballIndex++;
}
},
mounted() {
document.body.onclick=function(e){
// console.log(e.clientX,e.clientY)
}
}
})
</script>
</body>
抛物线公式 + 具体位置 + 不停变动 + 水平方向匀速 + 垂直方向加速