实现纵向切换内部可滚动的轮播

502 阅读1分钟

现在有一组简介,客户要求类似抖音一样纵向切换,但是简介内容一般超过一屏,需要滚动完一屏后才能切换到下一简介。

以为在slide里写个overflow: scroll 就可以了,没想到这个监听触摸事件优先级比页面滚动优先级更高一些。导致页面内不能滚动,向下滑就切换简介了。

动画.gif 遂翻文档,没找到官方例子。

遂谷歌,找到一个大神写好的代码

Swiper如何实现内容超出滑动 | Dull's Blog (dullly.github.io)

贴上去不行,下面讲一下按照我的实际情况去改动的部分。

问题

动画-1674633797188.gif

页面内可以滚动了,但是不能切换下一简介了。

经过调试,发现startScroll 也就是触摸开始时记录的当前页面滚动位置,不是整数而是小数。

这将导致滑动事件处理函数中的判断出现问题。

这里贴出经过我“美化”之后的代码,原代码见:

Swiper如何实现内容超出滑动 | Dull's Blog (dullly.github.io)

page_swiper.slides.on('touchmove', function (e) {
    touchCurrent = e.targetTouches[0].pageY
    const touchesDiff = touchCurrent - touchStart // 判断滑动方向
    const slide = this

    const hasScrollBar = slide.scrollHeight > slide.offsetHeight
    if (!hasScrollBar)
      return


    const frameOffset = slide.scrollHeight - slide.offsetHeight
    // 从顶部滚动到底部
    const topToBottom = touchesDiff < 0 && startScroll === 0
    // 从底部滚动到顶部
    const bottomToTop = touchesDiff > 0 && startScroll === frameOffset
    // 从中间开始
    const scrollMiddle = startScroll > 0 && startScroll < frameOffset

    const pageInnerScrolling = topToBottom || bottomToTop || scrollMiddle
    if (pageInnerScrolling)
      e.stopPropagation() // 终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。
  }, true)

刚才说到,startScroll 是小数,所以从底部滚动到顶部,startScroll一定不可能等于frameOffset(滚动内容与展示框的高度之差)

另外滚动到底部时的startScroll也一定不小于frameOffset,我的页面上打印出来startScroll=440.6xxxxx, frameOffset=441。

为什么出现小数?

因为我的页面使用了vw适配屏幕的单位,难免出现除不尽(当然也有计算机内部的问题)

详细请看(143条消息) 避坑08_解决scrollTop是小数造成的问题_ParadoxLin的博客-CSDN博客_scrolltop 小数

修复

所以我的改法便是加delta,这个误差大概+1-1

const frameOffset = slide.scrollHeight - slide.offsetHeight
// 从顶部滚动到底部
const topToBottom = touchesDiff < 0 && startScroll === 0
// 从底部滚动到顶部
const bottomToTop = touchesDiff > 0 && startScroll + 1 > frameOffset
// 从中间开始
const scrollMiddle = startScroll > 0 && startScroll + 1 < frameOffset

动画-1674638913017.gif