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>
相关推荐
福兮说16 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理17 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆66617 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
凤城老人17 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)17 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan18 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_19 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒19 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技19 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
yivifu20 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub