|
|
<template> <view class="centent"> <lf-nav :title="['分类','品牌'][current]" bgColor="#fff" :search="current == 0" @changeHeight="e => nav_height = e"></lf-nav> <view class="tabs"> <view class="lf-tab" :style="{width: 100 / tabs.length +'%'}" :class="{'tab-active': current == index}" v-for="(item, index) in tabs" :key="index" @click="current = index">{{ item.name }} </view> </view> <!-- 分类 --> <view class="page" v-if="current == 0"> <scroll-view class="left_view p_r" scroll-y :style="{ height: autoHeight }"> <block v-for="(item, index) in dataArr" :key="index"> <view :class="[left_selectIndex == index ? 'left_item_s' : '', 'left_item']" :id="'left_' + index" @click="leftTap({ item, index })">{{ item.name }}</view> </block> <view class="seletItem" :style="{ top: left_selectIndex * 60 - 19 + 'px' }"></view> </scroll-view> <scroll-view @scroll="rightScroll" class="right_view" scroll-y :style="{ height: autoHeight }" :scroll-into-view="'left_' + right_selectIndex" scroll-with-animation> <block v-for="(item, index) in dataArr" :key="index"> <view :ref="'left_' + index" class="right_item " :id="'left_' + index"> <text class="right_item_title ">{{ item.name }}</text> <view class="right_item_view"> <view class="item" v-for="(item, index) in item.subArr" :key="index" @click="rightTap(item)"> <image :src="item.img" :style="{ width: '100%', height: subItemW + 'px', background: '#999999' }"></image> <text class="lf-font-24">{{ item.name }}</text> </view> </view> </view> </block> <view class="" :style="{ height: autoScrollHeight }"><!-- 站位 --></view> </scroll-view> </view> <!-- 品牌 --> <view class="brand" v-else-if="current == 1" :style="{height: autoHeight}"> <!-- 筛选 --> <view class="lf-filter-box"> <view class="lf-filter" :class="{'lf-filter-after': filter_active == ''}"> <view :class="{'filter-active': filter_active == 'floor'}" @click="filter_active = 'floor'">楼层</view> <view :class="{'filter-active': filter_active == 'class'}" @click="filter_active = 'class'">分类</view> </view> <view class="filter-modal-mask" :style="{height: otherHeight}" v-if="filter_active != ''" @click="filter_active = ''"> <view class="filter-modal"> <view class="filter-item" v-for="(item, index) in 6" :key="index">{{ '哈哈'+ item }}</view> </view> </view> </view> <!-- 内容 --> <scroll-view class="brand-scroll" :scroll-into-view="scrollAnchorId" :scroll-y="true" :style="{height: otherHeight}"> <view class="lf-flex brand-item" :id="'anchor-'+ index" @click="$url('/pages/shop/shopdetail')" v-for="(item, index) in point_list" :key="index"> <image class="img" src="https://picsum.photos/200"></image> <view class="info"> <view class="lf-font-36 lf-font-bold lf-color-black">luckin coffee 瑞幸咖啡 {{ item }}</view> <view class="lf-font-24 lf-color-gray">餐饮·美食|18件在售</view> <view class="lf-font-24"> <text class="lf-iconfont icon--1 lf-font-24"></text> <text class="lf-color-gray lf-m-l-10">L2</text> </view> </view> </view> </scroll-view> <!-- 锚点定位 --> <view class="fixed-point" @touchmove="pointTouchmove"> <view class="point-item" @click="pointClick" :id="'point-'+index" :style="{height: 100 / 26 +'%'}" v-for="(item, index) in point_list" :key="index">{{ item }}</view> </view> </view> <lf-tabbar></lf-tabbar> </view></template>
<script> import lfNav from '@/components/lf-nav/lf-nav.vue'; import lfTabbar from '@/components/lf-tabbar/lf-tabbar.vue'; import testdata from './testdata.js'; let app = getApp(); export default { data() { return { scrollH: 0, subItemW: 0, left_selectIndex: 0, right_selectIndex: 0, ttscrollH: 0, //总高度
placeholderH: 0, //占位高度
heighArr: [], dataArr: testdata, current: 1, nav_height: 0, tabs: [{ name: '分类' },{ name: '品牌' }], filter_active: '', point_list: [], scrollAnchorId: '' }; }, computed: { autoHeight(){ return `calc(${this.scrollH}px - ${this.nav_height}px - 90rpx - 120rpx)`; }, otherHeight(){ // 屏幕可用总高度 - 导航条高度 - tabs高度 - tabbar高度 - 筛选高度
return `calc(${this.scrollH}px - ${this.nav_height}px - 90rpx - 120rpx - 105rpx)`; }, autoScrollHeight(){ return `calc(${this.scrollH}px - ${this.nav_height}px - 90rpx - 120rpx - 300rpx)`; } }, components: { lfNav, lfTabbar }, onLoad(options) { // https://ext.dcloud.net.cn/plugin?id=5031
if(this.$isRight(options)){ this.current = options.current || 1; this.left_selectIndex = options.type || 0; this.right_selectIndex = options.type || 0; } let info = uni.getSystemInfoSync(); let self = this; self.scrollH = info.screenHeight; self.subItemW = parseInt((info.screenWidth * (2 / 3) - 15 * 2 - 24) / 3); setTimeout(function() { self.computerH(); }, 100); this.createAtoZ(); }, methods: { // 生成A-Z的大写字母
createAtoZ(){ let point_list = []; for(var i=0; i<26; i++){ point_list.push(String.fromCharCode(65+i)); } this.point_list = point_list; }, pointTouchmove(event){ console.log(event); }, pointClick(event){ let index = (event.target.id).replace('point-', ''); let letter = this.point_list[index]; this.scrollAnchorId = ''; this.$msg(letter); this.$nextTick(() => { this.scrollAnchorId = 'anchor-'+ index; }) }, leftTap: function(e) { this.left_selectIndex = e.index; this.right_selectIndex = e.index; }, // 右边点击
rightTap: function() { this.$msg('敬请期待') }, rightScroll: function(e) { let scrollH = e.detail.scrollTop + 30; let cc = this.ttscrollH - this.scrollH; let a = 0; let findInx = this.heighArr.findIndex(function(itemH, i) { a = a + itemH; return a > scrollH; }); // if (scrollH >= cc) {
// return;
// }
this.left_selectIndex = findInx; }, // 计算高度
computerH: function() { this.ttscrollH = 0; for (let item of this.dataArr) { let title_lineH = 49; //rpx
let subNum = item.subArr.length; let subImgH = this.subItemW; //rpx
let subTitleH = 40; //rpx
let rowSpecH = 8; //rpx
let rowN = subNum % 3; let rowSpecNum = parseInt(subNum / 3) + parseInt(rowN > 0 ? 1 : 0); let totalRpx = title_lineH + (subImgH + subTitleH) * rowSpecNum + rowSpecH * (rowSpecNum - 1); this.heighArr.push(totalRpx); this.ttscrollH = this.ttscrollH + totalRpx; } // this.placeholderH = this.scrollH - this.heighArr[this.heighArr.length - 1];
//以下方法也可以
// let self=this
// var selectorQuery = uni.createSelectorQuery()
// selectorQuery.selectAll('.right_item').boundingClientRect(data => {
// self.heighArr = data.map(item => {
// return {
// top: Math.round(item.top),
// height: Math.round(item.height)
// }
// })
// }).exec()
// console.log('ttscrollH',this.$refs.left_0)
} } }</script>
<style lang="scss" scoped> .page { display: grid; grid-template-columns: 1fr 2fr; grid-template-rows: auto; position: absolute; left: 0rpx; right: 0rpx; overflow: hidden; box-sizing: border-box; } .left_view { background-color: #f4f8f8; position: relative; box-sizing: border-box; // 蒙版
.seletItem { height: 98px; position: absolute; top: 0rpx; left: 0rpx; z-index: 10; right: 0rpx; // background-color: rgba(255, 255, 255, 0.3);
transition: top 0.2s linear; display: flex; align-items: center; box-sizing: border-box; &::before { content: ''; width: 6rpx; height: 60%; background-color: #15716E; left: 0rpx; } } .left_item { display: flex; justify-content: center; align-items: center; height: 60px; margin-bottom: 0rpx; position: relative; font-size: 28rpx; box-sizing: border-box; color: #555555; } .left_item_s { background-color: #ffffff; color: #15716E; font-weight: bold; position: relative; box-sizing: border-box; } } .right_view { background-color: #ffffff; padding: 0rpx 12px; box-sizing: border-box; .right_item { .right_item_title { display: block; box-sizing: border-box; line-height: 49px; font-size: 28rpx; font-weight: bold; color: #15716E; } .right_item_view { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: auto; grid-gap: 8px 15px; box-sizing: border-box; .item { display: flex; flex-flow: column nowrap; align-items: center; box-sizing: border-box; text { color: #333; line-height: 40px; } } } } } .tabs{ width: 750rpx; height: 90rpx; display: flex; justify-content: space-between; border-bottom: 1rpx solid #e5e5e5; background-color: #FFFFFF; .lf-tab{ // width: 50%;
display: flex; align-items: center; justify-content: center; font-size: 28rpx; color: #777777; position: relative; &.tab-active{ color: #15716E; } &.tab-active::after{ content: ''; position: absolute; bottom: 0; left: 50%; width: 80rpx; height: 10rpx; background-color: #15716E; border-radius: 10rpx 10rpx 0 0; margin-left: -40rpx; } } } .lf-filter-box{ height: 105rpx; width: 750rpx; background-color: #F4F8F8; display: flex; justify-content: center; align-items: center; position: relative; .lf-filter{ width: 300rpx; height: 65rpx; border-radius: 33rpx; border: 1rpx solid #15716E; color: #15716E; font-size: 24rpx; display: flex; align-items: center; justify-content: space-between; position: relative; overflow: hidden; &.lf-filter-after::after{ content: ''; position: absolute; top: 12rpx; left: calc(50% - 1rpx); width: 2rpx; height: 40rpx; background-color: #15716E; } &>view{ height: 100%; width: 50%; display: flex; justify-content: space-around; align-items: center; } .filter-active{ background-color: #15716E; color: #FFFFFF; } } .filter-modal-mask{ position: absolute; top: 105rpx; left: 0; width: 100%; background-color: rgba(0,0,0,0.5); .filter-modal{ width: 750rpx; height: max-content; padding: 60rpx 32rpx; box-sizing: border-box; background-color: #FFFFFF; display: flex; flex-wrap: wrap; position: relative; z-index: 1; .filter-item{ width: 215rpx; height: 65rpx; border-radius: 10rpx; border: 1rpx solid #555555; display: flex; justify-content: center; align-items: center; font-size: 28rpx; color: #555555; margin-right: 21rpx; &:nth-child(3n){ margin-right: 0rpx; } &:nth-child(n+4){ margin-top: 21rpx; } } } } } .brand-scroll{ padding: 0rpx 32rpx; box-sizing: border-box; width: 750rpx; .brand-item{ margin-bottom: 60rpx; &:nth-child(1n){ margin-top: 30rpx; } } .img{ width: 150rpx; height: 150rpx; border-radius: 4rpx; margin-right: 20rpx; } .info{ width: 514rpx; height: 150rpx; display: flex; flex-direction: column; justify-content: space-between; } } .brand{ position: relative; } .fixed-point{ position: fixed; right: 0; top: 18vh; height: 70vh; width: 57rpx; background-color: rgba(0,0,0,0.3); border-radius: 30rpx 0rpx 0rpx 30rpx; padding: 14rpx 0rpx; z-index: 2; .point-item{ font-size: 24rpx; color: #FFFFFF; text-align: center; } }</style>
|