列表滚动选择与点击选择居中展示

核心需求描述  有一个边框高度为200,其中有30个列表竖着展示,边框是可以滚动的,每次滚动选中一个列表内容并添加一个class,滚动的时候内容一直是居中展示 列表也是可以点击选中

<!
DOCTYPE html> <html> <head> <style> .container { height: 200px; overflow: hidden; border: 1px solid #ccc; position: relative; } .list { list-style: none; padding: 0; margin: 0; position: absolute; top: 0; left: 0; width: 100%; transition: transform 0.2s ease; } .list-item { height: 40px; line-height: 40px; text-align: center; cursor: pointer; /* 鼠标悬浮指针 */ } .list-item.active { background: #007bff; color: white; } </style> </head> <body> <div class="container" id="container"> <ul class="list" id="list"> <!-- 30个列表项 --> <li class="list-item">项1</li> <li class="list-item">项2</li> <li class="list-item">项3</li> <li class="list-item">项4</li> <li class="list-item">项5</li> <li class="list-item">项6</li> <li class="list-item">项7</li> <li class="list-item">项8</li> <li class="list-item">项9</li> <li class="list-item">项10</li> <li class="list-item">项11</li> <li class="list-item">项12</li> <li class="list-item">项13</li> <li class="list-item">项14</li> <li class="list-item">项15</li> <li class="list-item">项16</li> <li class="list-item">项17</li> <li class="list-item">项18</li> <li class="list-item">项19</li> <li class="list-item">项20</li> <li class="list-item">项21</li> <li class="list-item">项22</li> <li class="list-item">项23</li> <li class="list-item">项24</li> <li class="list-item">项25</li> <li class="list-item">项26</li> <li class="list-item">项27</li> <li class="list-item">项28</li> <li class="list-item">项29</li> <li class="list-item">项30</li> </ul> </div> <script> const container = document.getElementById('container'); const list = document.getElementById('list'); const items = document.querySelectorAll('.list-item'); const itemHeight = 40; const containerCenter = container.clientHeight / 2; let currentIndex = 0; // 初始化选中第一个 items[currentIndex].classList.add('active'); // 核心滚动/选中逻辑 const scrollToIndex = (index) => { currentIndex = Math.max(0, Math.min(index, items.length - 1)); const translateY = containerCenter - (itemHeight * currentIndex + itemHeight / 2); list.style.transform = `translateY(${translateY}px)`; items.forEach((item, i) => item.classList.toggle('active', i === currentIndex)); }; // 滚轮事件 container.addEventListener('wheel', (e) => { e.preventDefault(); scrollToIndex(currentIndex + (e.deltaY > 0 ? 1 : -1)); }); // 点击事件 items.forEach((item, i) => { item.addEventListener('click', () => scrollToIndex(i)); }); </script> </body> </html>

效果图

imageimage

改成vue3

<template>
  <div class="container" ref="containerRef" @wheel="handleWheel">
    <ul class="list" :style="{ transform: `translateY(${translateY}px)` }">
      <li 
        v-for="(item, index) in 30" 
        :key="index" 
        class="list-item" 
        :class="{ active: currentIndex === index }"
        @click="scrollToIndex(index)"
      >
        项{{ index + 1 }}
      </li>
    </ul>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue';

// 响应式数据
const currentIndex = ref(0);
const containerRef = ref(null); // 容器DOM引用
const itemHeight = 40; // 列表项高度固定

// 计算容器中心位置(挂载后获取DOM尺寸)
const containerCenter = ref(0);

// 计算列表偏移量(响应式)
const translateY = computed(() => {
  return containerCenter.value - (itemHeight * currentIndex.value + itemHeight / 2);
});

// 核心滚动/选中逻辑
const scrollToIndex = (index) => {
  currentIndex.value = Math.max(0, Math.min(index, 29)); // 30项索引0-29
};

// 滚轮事件处理
const handleWheel = (e) => {
  e.preventDefault();
  scrollToIndex(currentIndex.value + (e.deltaY > 0 ? 1 : -1));
};

// 组件挂载后获取容器尺寸
onMounted(() => {
  if (containerRef.value) {
    containerCenter.value = containerRef.value.clientHeight / 2;
  }
});
</script>

<style scoped>
.container {
  height: 200px;
  overflow: hidden;
  border: 1px solid #ccc;
  position: relative;
}
.list {
  list-style: none;
  padding: 0;
  margin: 0;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  transition: transform 0.2s ease;
}
.list-item {
  height: 40px;
  line-height: 40px;
  text-align: center;
  cursor: pointer;
}
.list-item.active {
  background: #007bff;
  color: white;
}
</style>

 

posted @ 2025-12-01 14:04  瞎BB的是2B  阅读(4)  评论(0)    收藏  举报