uniapp 实现 列表滚动 支持自动滚动 手动滚动5秒后变成自动滚动

发布于:2025-06-19 ⋅ 阅读:(18) ⋅ 点赞:(0)

 

<template>
  <view style="padding: 200rpx 32rpx 0">
    <view class="view_box">
      <scroll-view
        class="scroll-container"
        :scroll-y="true"
        :scroll-top="scrollTop"
        @scroll="onScroll"
        @scrolltoupper="onScrollToUpper"
        @touchstart="handleTouchStart"
        @touchmove="handleTouchMove"
        @touchend="handleTouchEnd"
      >
        <view :style="transitionStyle" class="scroll-content">
          <template v-for="(item, index) in list">
            <view :key="index"> -------------{{ item }}---------- </view>
          </template>
        </view>
      </scroll-view>
    </view>
  </view>
</template>

<script>
export default {
  data () {
    return {
      transitionStyle: '',
      list: [],
      autoScrollTimer: null,
      resetTimer: null,
      isManualScrolling: false,
      startY: 0,
      lastTouch: 0,
      scrollTop: 0,
      isAutoScrolling: true,
      lastScrollTop: 0,
      scrollCheckTimer: null,
      noMovementTime: 0
    }
  },
  onShow () {
    // 示例 模拟接口请求
    this.getList().then(res => {
      console.log(res)
      this.list = [...res.data, ...res.data]
      // list赋值后调用初始化
      this.init()
    })
  },
  onHide () {
    // 页面隐藏时清除所有定时器
    this.clearAllTimers()
  },
  onUnload () {
    // 页面卸载时清除所有定时器
    this.clearAllTimers()
  },
  methods: {
    init () {
      // 清除可能存在的定时器
      this.clearAllTimers()

      // 启动自动滚动
      setTimeout(() => {
        this.startAutoScroll()
      }, 20)

      // 启动滚动检测
      this.startScrollDetection()
    },

    clearAllTimers () {
      if (this.autoScrollTimer) clearInterval(this.autoScrollTimer)
      if (this.resetTimer) clearTimeout(this.resetTimer)
      if (this.scrollCheckTimer) clearInterval(this.scrollCheckTimer)
    },

    startScrollDetection () {
      // 每200毫秒检查一次滚动位置,判断是否静止
      this.scrollCheckTimer = setInterval(() => {
        if (this.isManualScrolling && !this.isAutoScrolling) {
          if (this.scrollTop === this.lastScrollTop) {
            // 滚动位置没变,累加静止时间
            this.noMovementTime += 200

            // 如果3秒没有滚动,恢复自动滚动
            if (this.noMovementTime >= 3000) {
              console.log('检测到3秒无滚动,恢复自动滚动')
              this.isManualScrolling = false
              this.noMovementTime = 0
              this.startAutoScroll()
            }
          } else {
            // 有滚动,重置静止时间
            this.noMovementTime = 0
            this.lastScrollTop = this.scrollTop
          }
        }
      }, 200)
    },

    startAutoScroll () {
      if (this.isManualScrolling) return

      this.isAutoScrolling = true
      this.transitionStyle =
        'transition: all 8s linear 0s;transform: translateY(-50%);'

      // 设置自动滚动循环
      this.autoScrollTimer = setInterval(() => {
        this.transitionStyle = ''
        setTimeout(() => {
          if (!this.isManualScrolling) {
            this.transitionStyle =
              'transition: all 8s linear 0s;transform: translateY(-50%);'
          }
        }, 20)
      }, 5000)
    },

    stopAutoScroll () {
      this.isAutoScrolling = false
      if (this.autoScrollTimer) {
        clearInterval(this.autoScrollTimer)
        this.autoScrollTimer = null
      }

      // 获取当前位置并停止在该位置
      const currentTransform = this.transitionStyle.match(/translateY\((.+?)\)/)
      const currentY = currentTransform ? parseFloat(currentTransform[1]) : 0
      this.transitionStyle = `transform: translateY(${currentY}%);transition: none;`

      // 重置静止时间计数
      this.noMovementTime = 0
      this.lastScrollTop = this.scrollTop
    },

    handleTouchStart (e) {
      // 记录触摸开始时间
      this.lastTouch = Date.now()
      this.isManualScrolling = true

      // 停止自动滚动
      this.stopAutoScroll()

      // 清除恢复定时器
      if (this.resetTimer) {
        clearTimeout(this.resetTimer)
        this.resetTimer = null
      }

      // 记录起始位置
      this.startY = e.touches[0].clientY
      this.lastScrollTop = this.scrollTop
    },

    handleTouchMove (e) {
      this.lastTouch = Date.now()
      // 重置静止时间
      this.noMovementTime = 0
    },

    handleTouchEnd () {
      // 标记最后一次触摸时间
      this.lastTouch = Date.now()

      // 在手指抬起时记录当前滚动位置,作为静止检测的起始点
      this.lastScrollTop = this.scrollTop
    },

    onScroll (e) {
      if (e && e.detail) {
        this.scrollTop = e.detail.scrollTop
      }

      // 当用户手动滚动时,更新记录的最后触摸时间和重置静止时间
      if (!this.isAutoScrolling) {
        this.lastTouch = Date.now()
        this.noMovementTime = 0
      }
    },

    onScrollToUpper () {
      console.log('滚动到顶部')
    },

    // 模拟接口请求
    getList () {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve({
            code: '200',
            data: [1, 2, 3, 4, 5, 6, 7, 8, 9]
          })
        }, 200)
      })
    }
  }
}
</script>

<style lang="scss">
.view_box {
  background-color: pink;
  height: 200rpx;
  overflow: hidden;
}

.scroll-container {
  height: 100%;
  width: 100%;
}

.scroll-content {
  width: 100%;
}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到