Candice 1 week ago
parent 36e9335b2f
commit 7eab9cf071

@ -0,0 +1,172 @@
<template>
<scroll-view
ref="scrollRef"
class="scroll-container"
:scroll-x="direction === 'x'"
:scroll-y="direction === 'y'"
:scroll-with-animation="true"
:show-scrollbar="false"
:scroll-into-view="targetId"
@scroll="handleScroll"
:enable-flex="direction === 'x'?true:false"
>
<slot></slot>
</scroll-view>
</template>
<script setup>
import { ref, onMounted, nextTick, watch } from 'vue';
const props = defineProps({
// 'x' 'y'
direction: {
type: String,
default: 'y',
validator: (val) => ['x', 'y'].includes(val)
},
//
itemCount: {
type: Number,
required: true
},
//
activeIndex: {
type: Number,
default: 0
},
// ".list-item"
itemSelector: {
type: String,
required: true
},
// 0-1
thresholdRatio: {
type: Number,
default: 0.3
}
});
const emits = defineEmits(['update:activeIndex']);
const scrollRef = ref(null);
const targetId = ref(null);
const itemPositions = ref([]); //
const scrollViewInfo = ref(null); //
//
const getElementsInfo = (selector) => {
return new Promise(resolve => {
uni.createSelectorQuery()
.selectAll(selector)
.boundingClientRect(resolve)
.exec();
});
};
//
const getScrollViewInfo = () => {
return new Promise(resolve => {
uni.createSelectorQuery()
.select('.scroll-container')
.boundingClientRect(resolve)
.exec();
});
};
//
const initItemPositions = async () => {
await nextTick();
//
scrollViewInfo.value = await getScrollViewInfo();
console.log("test")
if (!scrollViewInfo.value) return;
//
const itemsInfo = await getElementsInfo(props.itemSelector);
if (!itemsInfo || itemsInfo.length === 0) return;
//
itemPositions.value = itemsInfo.map((item, index) => {
const scrollKey = props.direction === 'x' ? 'left' : 'top';
const sizeKey = props.direction === 'x' ? 'width' : 'height';
return {
index,
start: item[scrollKey] - scrollViewInfo.value[scrollKey],
end: item[scrollKey] - scrollViewInfo.value[scrollKey] + item[sizeKey],
size: item[sizeKey]
};
});
};
//
const scrollToIndex = (index) => {
if (index < 0 || index >= props.itemCount) return;
targetId.value = `${props.itemSelector.replace('.', '')}-${index}`;
// targetId
setTimeout(() => {
targetId.value = null;
}, 500);
};
//
const handleScroll = (e) => {
if (!itemPositions.value.length || !scrollViewInfo.value) return;
const scrollKey = props.direction === 'x' ? 'scrollLeft' : 'scrollTop';
const scrollPos = e.detail[scrollKey];
const containerSize = props.direction === 'x'
? scrollViewInfo.value.width
: scrollViewInfo.value.height;
//
for (let i = 0; i < itemPositions.value.length; i++) {
const item = itemPositions.value[i];
const threshold = item.size * props.thresholdRatio;
//
if (scrollPos >= (item.start - threshold) && scrollPos < (item.end - containerSize + threshold)) {
if (i !== props.activeIndex) {
emits('update:activeIndex', i);
}
break;
}
}
};
// activeIndex
watch(
() => props.activeIndex,
(newVal) => {
scrollToIndex(newVal);
console.log("init",itemPositions.value)
},
{ immediate: true }
);
// itemCount
watch(
() => props.itemCount,
async () => {
await initItemPositions();
}
);
//
onMounted(async () => {
await initItemPositions();
console.log("init",itemPositions.value)
});
//
defineExpose({
refreshPositions: initItemPositions
});
</script>
<style scoped lang="scss">
.scroll-container {
width: 100%;
}
</style>

@ -202,8 +202,103 @@
</view>
<text class="seeMore">查看更多></text>
</view>
<view class="swiperBox">
<swiper :indicator-dots="false" :autoplay="true" :circular="true" :interval="3000" :duration="1000"
:display-multiple-items="2.3" style="height: 400rpx;">
<swiper-item>
<view class="swiper-item">
<image class="swiper-img" src="/static/test/test3.png" mode="aspectFill"></image>
</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">
<image class="swiper-img" src="/static/test/test4.png" mode="aspectFill"></image>
</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">
<image class="swiper-img" src="/static/test/test5.png" mode="aspectFill"></image>
</view>
</swiper-item>
</swiper>
</view>
</view>
<diamondLine></diamondLine>
<view class="content content6">
<view class="barBox">
<view class="titleBox">
<text>成功案例</text>
<view class="purpleBox"></view>
</view>
<text class="seeMore">查看更多></text>
</view>
<view class="headBox">
<view class="headbar">
<view class="barItem" :class="activeOne === 0?'active':''" @click="changeBar(0)">
<text>同康美妆</text>
<view class="xiahuaxian" v-show="activeOne === 0"></view>
</view>
<view class="barItem" :class="activeOne === 1?'active':''" @click="changeBar(1)">
<text>中国药材</text>
<view class="xiahuaxian" v-show="activeOne === 1"></view>
</view>
<view class="barItem" :class="activeOne === 2?'active':''" @click="changeBar(2)">
<text>中国药材</text>
<view class="xiahuaxian" v-show="activeOne === 2"></view>
</view>
<view class="barItem" :class="activeOne === 3?'active':''" @click="changeBar(3)">
<text>中国药材</text>
<view class="xiahuaxian" v-show="activeOne === 3"></view>
</view>
<view class="barItem" :class="activeOne === 3?'active':''" @click="changeBar(3)">
<text>中国药材</text>
<view class="xiahuaxian" v-show="activeOne === 3"></view>
</view>
<view class="barItem" :class="activeOne === 3?'active':''" @click="changeBar(3)">
<text>中国药材</text>
<view class="xiahuaxian" v-show="activeOne === 3"></view>
</view>
<view class="barItem" :class="activeOne === 3?'active':''" @click="changeBar(3)">
<text>中国药材</text>
<view class="xiahuaxian" v-show="activeOne === 3"></view>
</view>
</view>
</view>
</view>
<view class="scroll11">
<view class="swiperBox">
<scroll-view scroll-x="true" scroll-y="false" class="scrollView" :enable-flex="true" :scroll-into-view="`scroll-${activeOne}`"
:show-scrollbar="false" scroll-with-animation="true" @touchmove.prevent="handleTouchMove" style="touch-action: none;">
<view class="scroll-item" v-for="(item,index) in 4" :id="`scroll-${index}`">
<image class="swiper-img" src="/static/test/test3.png" mode="widthFix"></image>
<text>{{index}}</text>
</view>
</scroll-view>
</view>
</view>
<!-- 使用封装的滚动组件 -->
<DIYScrollView
direction="x"
:itemCount="4"
:activeIndex="activeOne"
@update:activeIndex="val => activeOne = val"
itemSelector=".scroll-item"
class="list-scroll scrollView"
>
<view class="list" style="margin: 0 26rpx;">
<view class="scroll-item" v-for="(item,index) in 4" :id="`scroll-${index}`">
<image class="swiper-img" src="/static/test/test3.png" mode="widthFix"></image>
<text>{{index}}</text>
</view>
</view>
</DIYScrollView>
</view>
<tabbar :tabIndex="0"></tabbar>
@ -211,9 +306,21 @@
</template>
<script setup>
import { ref } from 'vue';
import { ref, nextTick } from 'vue';
import diamondLine from '../../components/diamondLine/diamondLine.vue';
import DIYScrollView from '../../components/DIYScrollView/DIYScrollView.vue';
const activeOne = ref(0)
const changeBar = (index)=>{
if(activeOne.value == index) return;
activeOne.value = index
nextTick()
console.log("1212",activeOne.value)
}
const handleTouchMove = (e)=> {
e.preventDefault(); //
return false; //
}
</script>
<style lang="scss" scoped>
@ -222,6 +329,7 @@ import diamondLine from '../../components/diamondLine/diamondLine.vue';
min-height: 100vh;
box-sizing: border-box;
position: relative;
background: #FAFBFF;
}
.indexBG{
width: 100%;
@ -761,4 +869,72 @@ import diamondLine from '../../components/diamondLine/diamondLine.vue';
}
}
}
.content5{
.swiperBox{
margin-top: 26rpx;
.swiper-img{
width: 272rpx;
height: 380rpx;
border-radius: 18rpx;
}
}
}
.content6{
.headbar{
margin: 26rpx;
min-height: 64rpx;
@include flexBox(start,center);
flex-wrap: nowrap;
overflow-x: auto;
white-space: nowrap;
scrollbar-width: none;
/* 隐藏 WebKit 内核浏览器Chrome、Safari、小程序等的滚动条 */
&::-webkit-scrollbar {
display: none;
/* 直接隐藏滚动条 */
}
.barItem{
flex-shrink: 0;
margin-right: 26rpx;
@include fontStyle(28rpx,#666666,left,400,38rpx);
position: relative;
.xiahuaxian{
position: absolute;
bottom: -14rpx;
left: 50%;
transform: translate(-50%,0);
width: 100%;
height: 0rpx;
border: 2rpx solid #000000;
}
&.active{
color: #000000 !important;
font-weight: bold !important;
}
}
}
}
.scroll11{
width: 100%;
.scrollView{
width: 100%;
@include flexBox(start,start);
// flex-wrap: nowrap;
overflow: auto;
.scroll-item{
width: 100%;
flex-shrink: 0; /* 核心:禁止子元素被压缩 */
box-sizing: border-box;
padding: 26rpx;
.swiper-img{
width: 100%;
height: auto;
}
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Loading…
Cancel
Save