hldy_app/component/public/game/ceshi.vue

129 lines
3.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>