效果图
本案例结合vant多选框
实现
这里只具体分析一下下拉框动画 内容多选效果 遮罩层
下拉框的实现
1、 通过对导航栏 position: fixed; top: 0px;transform: translate(-100%);
使他向上移动他自身高度的位置
这样子就实现了刚开始的导航栏隐藏
2、通过点击使导航栏移动到固定的位置
<template>
<div class="box">
<!-- 顶部 -->
<div class="top">
<div class="top-item">
<div>省份</div>
<div class="top-item">
<van-icon name="arrow-down" @click="control" />
</div>
</div>
<div class="top-item">
<div>级别</div>
<div class="top-item">
<van-icon name="arrow-down" />
</div>
</div>
</div>
<!-- 省份下拉展示框 -->
<div class="downBox" :class="[downflag?'downward':'',upflag?'upward':'']" ref="downBox">
<!-- 省份 -->
<div class="overSCroll">
<div
class="downBox-item"
v-for="(item,index) in provenceArr"
:key="index"
:id="index"
:style="{'color':(item.flag?'rgba(253, 16, 16, 100)':'')}"
@click="btnSelect(item,index)"
>{{item.provinceName}}{{`(${item.total})`}}</div>
</div>
<div class="downBox-bottom">
<div class="downBox-btn">重置</div>
<div class="downBox-btn btn-red" @click="control">确定</div>
</div>
</div>
<!-- 盒子撑起高度 -->
<div style="width: 100vw;height: 42px;"></div>
<!-- 内容 -->
<div class="content">
<!-- 遮罩层 -->
<div class="overCurtain" :style="{'display':(downflag?'block':'none')}"></div>
<div class="content-item">
<van-checkbox-group v-model="result">
<van-checkbox name="a">
<div class="radio-item">
<img
src="https://img2.baidu.com/it/u=2102736929,2417598652&fm=26&fmt=auto&gp=0.jpg"
alt
style="height:75px;width:100px;border-radius: 4px;"
/>
<div class="item-right">
<div class="name">南湖梦幻岛</div>
<div class="right-center">
<span style="font-size: 12px;">¥</span>
<span>39.9</span>
</div>
<div class="right-bottom">门票:98元</div>
</div>
</div>
</van-checkbox>
</van-checkbox-group>
</div>
</div>
<!-- 底部 -->
<div class="bottom">
<div class="bottom-left">
<div class="bottom-left-top">基础费用:¥39.90</div>
<div class="bottom-left-bottom">门票价值:¥98.00</div>
</div>
<button class="bottom-right">系统报价</button>
</div>
</div>
</template>
<script>
import travelApi from "@/travel";
import { formatProvince } from "@/utils";
export default {
data() {
return {
downBoxHeight: 0,
result: [],
downflag: false,
upflag: false,
listParams: {
limit: 40,
page: 0,
managerId: 0
},
provenceArr: []
};
},
computed: {},
watch: {},
mounted() {
document.title = "定制景区";
this.listParams.managerId = Number(this.$route.query.id);
this.getProvenceList();
},
methods: {
// 多选
btnSelect(item, index) {
// this.$set(this.selectArr, index, !this.selectArr[index]);
this.$set(item, "flag", !item.flag);
},
// 获得省份列表
getProvenceList() {
travelApi
.DZAreaList(this.listParams)
.then(res => {
if (res.status == 200) {
res.data.map(item => {
let obj = {};
obj.provinceId = item[0];
obj.provinceName = formatProvince(item[0]);
obj.total = item[1];
obj.flag = false;
this.provenceArr.push(obj);
});
this.selectArr = new Array(this.provenceArr.length).fill(false);
this.$nextTick(() => {
this.downBoxHeight = this.$refs.downBox.clientHeight;
});
}
console.log(this.provenceArr, "我来了");
console.log(this.downBoxHeight, "高度");
console.log(this.selectArr, "数据");
})
.catch(err => {
console.log(err);
});
},
// control控制是否展开
control() {
console.log("我点到了");
this.downflag = !this.downflag;
this.upflag = !this.downflag;
console.log(this.provenceArr, "通过flag为true 选择想对象的数据");
}
}
};
</script>
<style lang='scss' scoped>
.box {
background-color: rgba(246, 246, 246, 100);
min-height: 100vh;
width: 100vw;
// 顶部
.top {
width: 100vw;
height: 42px;
display: flex;
align-items: center;
justify-content: space-around;
background-color: rgba(248, 248, 248, 100);
position: fixed;
top: 0px;
z-index: 102;
.top-item {
display: flex;
align-items: flex-end;
}
}
// 内容区
.content-item {
width: calc(100% - 17px);
height: 100px;
padding-left: 17px;
border-radius: 6px;
background-color: rgba(255, 255, 255, 100);
margin-bottom: 8px;
display: flex;
align-items: center;
.radio-item {
display: flex;
align-items: center;
width: 100%;
.item-right {
margin-left: 10px;
height: 75px;
.name {
color: rgba(0, 0, 0, 1);
font-size: 14px;
height: 33%;
display: flex;
align-items: flex-start;
}
.right-center {
color: rgba(253, 16, 16, 100);
font-size: 16px;
height: 33%;
display: flex;
align-items: center;
}
.right-bottom {
color: rgba(140, 140, 140, 100);
font-size: 11px;
height: 33%;
display: flex;
align-items: flex-end;
}
}
}
}
// 底部
.bottom {
position: fixed;
bottom: 0px;
width: calc(100vw - 34px);
height: 54px;
padding: 0 17px;
background: white;
display: flex;
align-items: center;
justify-content: space-between;
.bottom-left {
.bottom-left-top {
color: rgba(0, 0, 0, 1);
font-size: 18px;
}
.bottom-left-bottom {
color: rgba(117, 117, 117, 100);
font-size: 10px;
}
}
.bottom-right {
border-radius: 6px;
background-color: rgba(253, 16, 16, 100);
width: 137px;
height: 38px;
border: none;
outline: none;
color: rgba(255, 255, 255, 100);
font-size: 18px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
// 遮罩层
.overCurtain {
border-top: 1px solid rgb(230, 245, 255);
position: absolute;
height: calc(100vh - 1px);
width: 100%;
left: 0px;
top: 0px; /*从左上角开始,覆盖整个页面*/
opacity: 0.7; /*透明度*/
background-color: black;
z-index: 100; /*层,重叠时大的优先显示,默认为0。登陆框可以设为101*/
display: none; /*开始不显示*/
}
.overSCroll {
max-height: 205px;
overflow: scroll;
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: space-between;
}
// 下拉
.downBox {
width: calc(100vw - 42px);
border-radius: 0px 0px 8px 8px;
background: white;
position: fixed;
top: 0px;
transform: translate(-100%);
padding: 20px 21px 30px 21px;
z-index: 101;
}
// 下拉框内容
.downBox-item {
width: 30%;
height: 40px;
line-height: 40px;
text-align: center;
}
.downBox-bottom {
margin-top: 15px;
width: 100%;
align-items: center;
display: flex;
justify-content: space-between;
}
.downBox-btn {
border: 1px solid rgba(111, 111, 111, 100);
border-radius: 57px;
width: 174px;
height: 38px;
display: flex;
justify-content: center;
align-items: center;
color: rgba(34, 34, 34, 100);
font-size: 14px;
}
.btn-red {
border-radius: 57px;
background-color: rgba(250, 49, 28, 100);
border: none;
color: white;
}
.downward {
animation: downAnimation 0.5s ease-in;
animation-fill-mode: forwards;
}
@keyframes downAnimation {
from {
transform: translateY(-100%);
}
to {
transform: translateY(calc(0% + 42px));
}
}
.upward {
animation: upAnimation 0.5s ease-in;
animation-fill-mode: forwards;
}
@keyframes upAnimation {
from {
transform: translateY(calc(0% + 42px));
}
to {
transform: translateY(-100%);
}
}
</style>