Browse Source

feat: 支持气泡展示滚动列表当前项目

v1.0.1
jiannibang 3 years ago
parent
commit
f30225b32a
  1. 5
      src/base/ScrollView/ScrollView.vue
  2. 74
      src/components/BrandScroll/BrandScroll.vue
  3. 38
      src/components/BrandScroll/getTranslateValues.js
  4. 4
      src/views/Guide/Guide.vue

5
src/base/ScrollView/ScrollView.vue

@ -41,10 +41,6 @@ const props = defineProps({
autoTop: {
type: Boolean,
default: true
},
indicators: {
type: Object,
default: undefined
}
})
@ -68,7 +64,6 @@ function _initScroll() {
observeImage: props.observeImage,
probeType: props.probeType,
indicators: document.getElementById('indicator') ? [{ relationElement: document.getElementById('indicator'), relationElementHandleElementIndex: 0 }] : undefined
// ...(props.indicators ? { indicators: props.indicators } : {})
})
}

74
src/components/BrandScroll/BrandScroll.vue

@ -1,12 +1,17 @@
<template>
<ScrollView
ref="scroll"
:indicators="!indicatorWrapper ? undefined : [{ relationElement: indicatorWrapper, relationElementHandleElementIndex: 0 }]"
:class="['brand-scroll', $route.path === '/guide' ? 'guide' : 'brand']"
scrollbar
>
<div class="brand-content">
<div class="groups" v-for="item of list" v-show="item.shopList.length" :key="item.name">
<ScrollView ref="scroll" :class="['brand-scroll', $route.path === '/guide' ? 'guide' : 'brand']" scrollbar>
<div class="brand-content" ref="content">
<div
class="groups"
v-for="(item, i) of list"
:ref="
el => {
groups[i] = el
}
"
v-show="item.shopList.length"
:key="item.name"
>
<h1 class="info">
{{ item.name }}<span class="meta">/ {{ item.shopList.length }}</span>
<span v-if="item.name === currentFloor.floor" class="current" id="current">您在本层</span>
@ -26,22 +31,57 @@
</TransitionGroup>
</div>
</div>
<!-- <div class="indicator" id="indicator" ref="indicatorWrapper">
<div class="handle"></div>
</div> -->
<div class="indicator" :style="{ visibility: hasScollBar ? 'visible' : 'hidden' }" id="indicator" ref="indicatorWrapper">
<div class="handle">{{ list[indicatorIndex]?.name }}</div>
</div>
</ScrollView>
</template>
<script setup>
import { ref, nextTick, watch } from 'vue'
import { ref, nextTick, watch, computed } from 'vue'
import ShopItem from '@/base/ShopItem/ShopItem.vue'
import ScrollView from '@/base/ScrollView/ScrollView.vue'
import { storeToRefs } from 'pinia'
import { useStore } from '@/store/root'
import { useElementSize, useMutationObserver } from '@vueuse/core'
import { getTranslateValues } from './getTranslateValues'
const store = useStore()
const { currentFloor } = storeToRefs(store)
const indicatorWrapper = ref(null)
const scroll = ref(null)
const content = ref(null)
const groups = ref([])
const { height: containerHeight } = useElementSize(scroll)
const { height: contentHeight } = useElementSize(content)
const hasScollBar = computed(() => containerHeight.value < contentHeight.value)
const heights = computed(() => groups.value.map(useElementSize).map(({ height }) => height))
const bounds = computed(() =>
heights.value.reduce((acc, nxt, i) => {
const arr = [...acc]
arr[i] = i === 0 ? nxt.value : arr[i - 1] + nxt.value
return arr
}, [])
)
const y = ref(0)
const indicatorIndex = computed(() =>
bounds.value.findIndex((el, i) => {
const start = 40 - y.value
if (i === 0 && start < el) return true
return start > bounds.value[i - 1] && start < el
})
)
useMutationObserver(
content,
([{ attributeName, target }]) => {
if (attributeName === 'style') y.value = getTranslateValues(target).y
},
{
attributes: true
}
)
const props = defineProps({
list: Array,
config: Object,
@ -55,6 +95,7 @@ const emits = defineEmits(['click'])
function handleShop(item) {
emits('click', item)
}
watch(
() => props.isRow,
() =>
@ -106,11 +147,19 @@ watch([scroll, () => props.shop], () => {
top: 102px;
right: 43px;
width: 77px;
pointer-events: none;
.handle {
position: absolute;
width: 77px;
height: 32px;
background: center / cover no-repeat url(./handle.png);
font-family: 'Montserrat';
font-style: normal;
font-weight: 700;
font-size: 14px;
line-height: 32px;
color: rgba(0, 0, 0, 0.8);
text-align: center;
}
}
&.guide {
@ -146,6 +195,7 @@ watch([scroll, () => props.shop], () => {
background: #ffffff !important;
border-radius: 6px !important;
border: none !important;
margin-top: -50%;
}
}
}

38
src/components/BrandScroll/getTranslateValues.js

@ -0,0 +1,38 @@
export function getTranslateValues(element) {
const style = window.getComputedStyle(element)
const matrix = style['transform'] || style.webkitTransform || style.mozTransform
// No transform property. Simply return 0 values.
if (matrix === 'none' || typeof matrix === 'undefined') {
return {
x: 0,
y: 0,
z: 0
}
}
// Can either be 2d or 3d transform
const matrixType = matrix.includes('3d') ? '3d' : '2d'
const matrixValues = matrix.match(/matrix.*\((.+)\)/)[1].split(', ')
// 2d matrices have 6 values
// Last 2 values are X and Y.
// 2d matrices does not have Z value.
if (matrixType === '2d') {
return {
x: matrixValues[4],
y: matrixValues[5],
z: 0
}
}
// 3d matrices have 16 values
// The 13th, 14th, and 15th values are X, Y, and Z
if (matrixType === '3d') {
return {
x: matrixValues[12],
y: matrixValues[13],
z: matrixValues[14]
}
}
}

4
src/views/Guide/Guide.vue

@ -226,7 +226,9 @@ function filterAboutCurrentInfo() {
const floorOrder = shop.value ? shop.value.floorOrder : currentFloor.value.floorOrder
try {
window.Map_QM.showFloor(floorOrder)
} catch (error) {}
} catch (error) {
console.warn(error)
}
floorIdx.value = currentBuildingFloorsList.value.findIndex(item => item.floorCode === floorCode)
selectedShopList.value = shopList.value.map(brand => ({
...brand,

Loading…
Cancel
Save