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

javascript 复制代码
<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>
相关推荐
花生侠18 分钟前
记录:前端项目使用pnpm+husky(v9)+commitlint,提交代码格式化校验
前端
猿榜19 分钟前
魔改编译-永久解决selenium痕迹(二)
javascript·python
阿幸软件杂货间23 分钟前
阿幸课堂随机点名
android·开发语言·javascript
一涯25 分钟前
Cursor操作面板改为垂直
前端
我要让全世界知道我很低调32 分钟前
记一次 Vite 下的白屏优化
前端·css
threelab32 分钟前
three案例 Three.js波纹效果演示
开发语言·javascript·ecmascript
1undefined234 分钟前
element中的Table改造成虚拟列表,并封装成hooks
前端·javascript·vue.js
蓝倾1 小时前
淘宝批量获取商品SKU实战案例
前端·后端·api
comelong1 小时前
Docker容器启动postgres端口映射失败问题
前端