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>
相关推荐
To_OC10 小时前
LC 17 电话号码的字母组合:我的回溯算法,就是从这道题开窍的
javascript·算法·leetcode
vipbic10 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy11 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志11 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble12 小时前
c端系统,其实更像一个信息展示平台
前端
你怎么知道我是队长12 小时前
JavaScript的变量和数据类型介绍
开发语言·javascript·ecmascript
李姆斯13 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜14 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js
广州灵眸科技有限公司14 小时前
瑞芯微RV1126B开发板(EASY-EAI-PI2) INI文件操作
java·前端·javascript·网络·人工智能
心中有国也有家14 小时前
AtomGit Flutter 鸿蒙客户端:ModalBottomSheet 实战
android·javascript·学习·flutter·华为·harmonyos