vue3 实现一个列表水平居中的同时,可以左右滑动?

vue3 实现一个列表水平居中的同时,可以左右滑动?通过添加display: flex;justify-content: center; 实现了prize-pools-box中元素的居中,但是现在元素无法向左滚动了,vue3 想实现一个列表水平居中的同时,可以左右滑动? 应该怎么改呢?这个功能需要适配低版本浏览器和低版本手机,有什么兼容的方法吗?

<div class="prize-pools-box">
            <div class="prize-item" :key="index" v-for="(item, index) in 9"></div>
</div>
  .prize-pools-box {
      margin-top: 27px;
      width: 100vw;
      height: 182px;
      display: flex;
      overflow-x: auto;
      overflow-y: hidden;
      position: relative;
      justify-content: center;
      .prize-item {
        width: 173px;
        height: 182px;
        margin-right: 12px;
}
}
阅读 2.9k
3 个回答
<template>
    <div class="prize-pools-container">
        <div class="prize-pools-box">
            <div v-for="(item, index) in items" :key="index" class="prize-pool-item">
                {{ item }}
            </div>
        </div>
    </div>
</template>
<script setup>
const items= ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7']

</script>
<style>

.prize-pools-container {
    display: flex;
    justify-content: center;
    overflow-x: hidden; /* 防止容器本身滚动 */
}

.prize-pools-box {
    display: flex;
    overflow-x: auto; /* 允许子元素水平滚动 */
    scroll-snap-type: x mandatory; /* 启用滚动捕捉 */
    padding: 0 16px; /* 两端留出一些空间,防止滚动时边缘卡顿 */
    -webkit-overflow-scrolling: touch; /* 使 iOS 设备上的滚动更流畅 */
}

.prize-pool-item {
    flex-shrink: 0; /* 防止子元素缩小 */
    width: 100px; /* 示例宽度,可以根据需要调整 */
    height: 100px; /* 示例高度,可以根据需要调整 */
    margin: 0 8px; /* 子元素之间的间距 */
    background-color: #f0f0f0; /* 示例背景色 */
    display: flex;
    align-items: center;
    justify-content: center;
    scroll-snap-align: start; /* 启用滚动捕捉 */
}
</style>

效果如下
image.png

<template>
  <div class="outer-container">
    <div class="inner-container" ref="scrollContainer">
      <div class="prize-pools-box">
        <div 
          class="prize-item" 
          v-for="(item, index) in 9" 
          :key="index"
        ></div>
      </div>
    </div>
  </div>
</template>

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

const scrollContainer = ref(null)
let startX = 0
let scrollLeft = 0
let isDown = false

const handleMouseDown = (e) => {
  isDown = true
  startX = e.pageX - scrollContainer.value.offsetLeft
  scrollLeft = scrollContainer.value.scrollLeft
}

const handleMouseUp = () => {
  isDown = false
}

const handleMouseMove = (e) => {
  if (!isDown) return
  e.preventDefault()
  const x = e.pageX - scrollContainer.value.offsetLeft
  const walk = (x - startX) * 2
  scrollContainer.value.scrollLeft = scrollLeft - walk
}

onMounted(() => {
  const el = scrollContainer.value
  if (el) {
    el.style.transform = 'translateZ(0)'
    el.style.willChange = 'transform'

    el.addEventListener('mousedown', handleMouseDown)
    el.addEventListener('mouseleave', handleMouseUp)
    el.addEventListener('mouseup', handleMouseUp)
    el.addEventListener('mousemove', handleMouseMove)
  }
})

onUnmounted(() => {
  const el = scrollContainer.value
  if (el) {
    el.removeEventListener('mousedown', handleMouseDown)
    el.removeEventListener('mouseleave', handleMouseUp)
    el.removeEventListener('mouseup', handleMouseUp)
    el.removeEventListener('mousemove', handleMouseMove)
  }
})
</script>

<style lang="scss" scoped>
.outer-container {
  width: 100%;
  overflow: hidden;
  position: relative;
}

.inner-container {
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch; /* 增强 iOS 滚动体验 */
  margin: 0 auto;
  /* 隐藏滚动条但保持功能 */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
  &::-webkit-scrollbar {
    display: none; /* Chrome, Safari, Opera */
  }
}

.prize-pools-box {
  margin-top: 27px;
  display: -webkit-inline-flex;
  display: -ms-inline-flexbox;
  display: inline-flex;
  padding: 0 calc(50% - 86.5px); /* 半个容器宽度减去半个item宽度 */
  
  scroll-behavior: smooth;
  -webkit-scroll-behavior: smooth;
  
  .prize-item {
    flex-shrink: 0; 
    width: 173px;
    height: 182px;
    margin-right: 12px;
    background-color: #f0f0f0; 
    
    &:last-child {
      margin-right: 0;
    }
  }
}

@media (hover: none) and (pointer: coarse) {
  .inner-container {
    -webkit-overflow-scrolling: touch;
    -ms-overflow-style: -ms-autohiding-scrollbar;
  }
}

@supports (-webkit-touch-callout: none) {
  .inner-container {
    /* iOS Safari specific styles */
    -webkit-overflow-scrolling: touch;
  }
}
</style>

还可以定制参数:

<script setup>
const props = defineProps({
  items: {
    type: Array,
    default: () => Array(9).fill({})
  },
  itemWidth: {
    type: Number,
    default: 173
  },
  itemHeight: {
    type: Number,
    default: 182
  },
  itemGap: {
    type: Number,
    default: 12
  }
})
</script>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏