hldy_app/component/public/game/ceshi.vue

129 lines
3.5 KiB
Vue
Raw Normal View History

2025-04-28 17:33:10 +08:00
<template>
<view class="container">
<scroll-view id="scrollContainer" ref="scrollViewRef" class="scroll-view" scroll-y :scroll-top="scrollTop"
@scroll="onScroll">
<view v-for="(item, index) in items" :key="index" class="item" :class="{ active: index === activeIndex }"
:style="{ marginLeft: marginList[index] + 'rpx' }">
{{ item }}
</view>
</scroll-view>
</view>
</template>
<script setup>
import {
ref,
onMounted,
nextTick,
getCurrentInstance
} from 'vue';
const {
proxy
} = getCurrentInstance();
const scrollViewRef = ref(null);
// 原始列表数据及状态
const originalItems = Array.from({
length: 20
}, (_, i) => `列表项 ${i+1}`);
const items = ref([]);
const marginList = ref([]);
const activeIndex = ref(0);
const scrollTop = ref(0);
let offsetCount = 0;
// 计算各项 margin 并更新高亮
function updateMargins(scrollY) {
const query = uni.createSelectorQuery().in(proxy);
query.select('#scrollContainer').boundingClientRect();
query.selectAll('.item').boundingClientRect();
query.exec(res => {
const [scrollRect, itemRects] = res;
if (!scrollRect || !itemRects) return;
const centerY = scrollRect.height / 2;
const maxMargin = 300; // ← 从 60 调到 120偏移加倍
const maxDist = centerY;
itemRects.forEach((r, i) => {
const itemCenter = r.top - scrollRect.top + r.height / 2;
const dist = Math.abs(itemCenter - centerY);
const t = Math.min(dist / maxDist, 1);
const eased = 1 - Math.cos(t * Math.PI / 2);
const m = eased * maxMargin;
marginList.value[i] = Math.round(m);
});
// 剩下高亮逻辑不变
const slice = marginList.value.slice(offsetCount, offsetCount + originalItems.length);
const minM = Math.min(...slice);
activeIndex.value = slice.indexOf(minM) + offsetCount;
});
}
// 滚动时触发
const scrollTimeout = ref(null);
const onScroll = (e) => {
nextTick(() => updateMargins(e.detail.scrollTop));
// 检测停止滚动
if (scrollTimeout.value) clearTimeout(scrollTimeout.value);
scrollTimeout.value = setTimeout(() => {
// 滚动停止后的处理逻辑
console.log('滚动已停止');
console.log("??????????????", activeIndex.value - 8)
// 你可以在这里触发居中对齐、播放动画等
}, 100); // 100ms 内未触发 scroll判定为停止
};
onMounted(async () => {
// 初始先用原始列表测量高度
items.value = originalItems;
marginList.value = Array(items.value.length).fill(0);
await nextTick();
const query = uni.createSelectorQuery().in(proxy);
query.select('#scrollContainer').boundingClientRect();
query.selectAll('.item').boundingClientRect();
query.exec(res => {
const [scrollRect, itemRects] = res;
if (!scrollRect || !itemRects || !itemRects.length) return;
const itemH = itemRects[0].height;
offsetCount = Math.ceil((scrollRect.height / 2) / itemH) + 3;
// 重构带占位的列表
items.value = [
...Array(offsetCount).fill(''),
...originalItems,
...Array(offsetCount).fill(''),
];
marginList.value = Array(items.value.length).fill(0);
// 设置初始滚动位置
scrollTop.value = offsetCount * itemH;
nextTick(() => updateMargins(scrollTop.value));
});
});
</script>
<style scoped>
.container {
height: 800rpx;
position: absolute;
bottom: 300rpx;
right: 100rpx;
overflow: hidden;
z-index: 100;
}
.scroll-view {
height: 100%;
}
.item {
padding: 10px;
/* transition: color 0.2s; */
}
.active {
color: red;
}
</style>