我的购物小球是从'去结算'那里出来,请帮我看看为什么会这样
来源:17-20 购物车小球动画实现(3)
qq_上帝之手_3
2018-01-10
<template>
<div class="shopcart">
<div class="content">
<div class="content-left">
<div class="logo-wrapper">
<!-- :class="{'highLight':totalCount>0}"当totalCount>0时,只要我们选择了商品,显示class为highLight的样式 -->
<div class="logo" :class="{'highlight':totalCount>0}">
<i class="icon-shopping_cart" :class="{'highlight':totalCount>0}"></i>
</div>
<div class="num" v-show="totalCount>0">{{totalCount}}</div>
</div>
<div class="price" :class="{'highlight':totalPrice>0}">¥{{totalPrice}}元</div>
<div class="desc">另需配送费¥{{deliveryPrice}}元</div>
</div>
<div class="content-right">
<!-- 多少钱起送 -->
<div class="pay" :class="payClass">{{payDesc}}</div>
</div>
</div>
<div class="ball-container">
<div v-for="ball in balls">
<transition name="drop" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
<div class="ball" v-show="ball.show">
<div class="inner inner-hook"></div>
</div>
</transition>
</div>
</div>
</div>
</template>
<script>
import BScroll from "better-scroll";
import cartcontrol from "components/cartcontrol/cartcontrol";
export default {
props: {
//shopcart组件传进来的变量要用props接收
selectFoods: {
//selectFoods保存了一个选择商品的数组,price就可以根据整个数组进行计算了
type: Array,
default() {
//如果default的值是Object或者Array,default就必需写成一个函数
return [
{
price: 30,
count: 1
}
]; //return一个空数组
}
},
deliveryPrice: {
type: Number, //变成习惯,prop属性一般最好指定数据类型
default: 0 //默认值是0
},
minPrice: {
type: Number,
default: 0
}
},
data() {
return {
balls: [
//抛物线小球需要创建一个数组
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
}
],
dropBalls: [], //已经下落的小球,数组//观测所有下落的小球
fold: true
};
},
computed: {
//利用计算属性表示price
totalPrice() {
//totalPrice依赖于selectFoods
let total = 0;
this.selectFoods.forEach(food => {
//遍历数组
total += food.price * food.count; //food指的是当前食物的数量
});
return total;
},
totalCount() {
let count = 0;
this.selectFoods.forEach(food => {
count += food.count; //把所有选择了的都加起来
});
return count;
},
payDesc() {
if (this.totalPrice === 0) {
//当总价是0的时候默认显示20元起送
return `¥${this.minPrice}元起送`; //用``代替用+号拼接字符串,写起来更加方便
} else if (this.totalPrice < this.minPrice) {
//当总价低于最低起送价时显示还差##元起送
let diff = this.minPrice - this.totalPrice; //声明一个变量说明离最低起送价还差多少
return `还差¥${diff}元起送`;
} else {
//剩下的就是满足条件的了
return "去结算"; //没有变量的时候就用普通的单引号就可以了
}
},
payClass() {
//根据实际情况切换enough或者not-enough的class属性
if (this.totalPrice < this.minPrice) {
return "not-enough";
} else {
return "enough";
}
}
},
methods: {
drop(el) {
//el指元素
console.log(el);
for (let i = 0; i < this.balls.length; i++) {
let ball = this.balls[i]; //拿到一个ball
if (!ball.show) {
//如果ball没有出现
ball.show = true;
ball.el = el;
this.dropBalls.push(ball); //将出现的ball加入dropBalls
return; //然后跳出循环
}
}
},
addFood(target) {
this.drop(target);
},
beforeEnter(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; //32是小球的left偏移
let y = -(window.innerHeight - rect.top - 22);
el.style.display = "";
el.style.webkitTransform = `translate3d(0,${y}px,0)`;
el.style.transform = `translate3d(0,${y}px,0)`;
let inner = el.getElementsByClassName("inner-hook")[0];
el.style.webkitTransform = `translate3d(${x}px,0,0)`;
el.style.transform = `translate3d(${x}px,0,0)`;
}
}
},
enter(el, done) {
//触发浏览器重绘,enter就重置回来
/*eslint-disable no-used-vars */
let rf = el.offsetHeight;
this.$nextTick(() => {
el.style.webkitTransform = "translate3d(0,0,0)"; //没有任何变量的时候要用单引号
el.style.transform = "translate3d(0,0,0)";
let inner = el.getElementsByClassName("inner-hook")[0];
el.style.webkitTransform = "translate3d(0,0,0)";
el.style.transform = "translate3d(0,0,0)";
el.addEventListener('transitionend', done);
});
},
afterEnter(el) {
let ball = this.dropBalls.shift();
if (ball) {
ball.show = false;
el.style.display = "none";
}
}
}
};
</script>
<style lang="stylus" type="stylesheet/stylus">
@import '../common/stylus/mixin.styl';
.shopcart
position: fixed
left: 0
bottom: 0
z-index: 50
width: 100%
height: 48px
.content
display: flex
background: #141d27
font-size: 0
color: rgba(255, 255, 255, 0.4)
.content-left
flex: 1
.logo-wrapper
display: inline-block
vertical-align: top
position: relative
top: -10px
margin: 0 12px
padding: 6px
width: 56px
height: 56px
box-sizing: border-box
border-radius: 50%
background: #141d27
.logo
width: 100%
height: 100%
border-radius: 50%
text-align: center
background: #2b343c
&.highlight
background: rgb(0, 160, 220)
.icon-shopping_cart
line-height: 44px
font-size: 24px
color: #80858a
&.highlight
color: #fff
.num
position: absolute
top: 0
right: 0
width: 24px
height: 16px
line-height: 16px
text-align: center
border-radius: 16px
font-size: 9px
font-weight: 700
color: #fff
background: rgb(240, 20, 20)
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4)
.price
display: inline-block
vertical-align: top
margin-top: 12px
line-height: 24px
padding-right: 12px
box-sizing: border-box
border-right: 1px solid rgba(255, 255, 255, 0.1)
font-size: 16px
font-weight: 700
&.highlight
color: #fff
.desc
display: inline-block
vertical-align: top
margin: 12px 0 0 12px
line-height: 24px
font-size: 10px
.content-right
flex: 0 0 105px
width: 105px
.pay
height: 48px
line-height: 48px
text-align: center
font-size: 12px
font-weight: 700
&.not-enough
background: #2b333b
&.enough
background: #00b43c
color: #fff
.ball-container
.ball
position: fixed
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
.shopcart-list
position: absolute
left: 0
top: 0
z-index: -1
width: 100%
transform: translate3d(0, -100%, 0)
&.fold-enter-active, &.fold-leave-active
transition: all 0.5s
&.fold-enter, &.fold-leave-active
transform: translate3d(0, 0, 0)
.list-header
height: 40px
line-height: 40px
padding: 0 18px
background: #f3f5f7
border-bottom: 1px solid rgba(7, 17, 27, 0.1)
.title
float: left
font-size: 14px
color: rgb(7, 17, 27)
.empty
float: right
font-size: 12px
color: rgb(0, 160, 220)
.list-content
padding: 0 18px
max-height: 217px
overflow: hidden
background: #fff
.food
position: relative
padding: 12px 0
box-sizing: border-box
border-1px(rgba(7, 17, 27, 0.1))
.name
line-height: 24px
font-size: 14px
color: rgb(7, 17, 27)
.price
position: absolute
right: 90px
bottom: 12px
line-height: 24px
font-size: 14px
font-weight: 700
color: rgb(240, 20, 20)
.cartcontrol-wrapper
position: absolute
right: 0
bottom: 6px
.list-mask
position: fixed
top: 0
left: 0
width: 100%
height: 100%
z-index: 40
backdrop-filter: blur(10px)
opacity: 1
background: rgba(7, 17, 27, 0.6)
&.fade-enter-active, &.fade-leave-active
transition: all 0.5s
&.fade-enter, &.fade-leave-active
opacity: 0
background: rgba(7, 17, 27, 0)
</style>
//我的购物小球是从'去结算'那里出来,请帮我看看为什么会这样,它现在是一条直线而不是抛物线
3回答
-
qq_上帝之手_3
提问者
2018-01-10
通过一行一行对代码,终于找到了原因,可以睡个安稳觉了,谢谢
00 -
qq_上帝之手_3
提问者
2018-01-10
beforeEnter(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; //32是小球的left偏移
let y = -(window.innerHeight - rect.top - 22);//获取y
el.style.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.style.webkitTransform = `translate3d(${x}px,0,0)`;
inner.style.transform = `translate3d(${x}px,0,0)`;
}
}
},
//我已经改了beforeEnter(el) 的代码,它变成只能竖着掉小球了
012018-01-11 -
ustbhuangyi
2018-01-10
你这个代码贴的太难以阅读了,建议对比一下源码吧:https://github.com/ustbhuangyi/vue-sell
00
相似问题