Jealh's Blog

𝓣𝓱𝓲𝓼 𝓲𝓼 𝓪 𝓫𝓮𝓪𝓾𝓽𝓲𝓯𝓾𝓵 𝓼𝓾𝓫𝓽𝓲𝓽𝓵𝓮

0%

Scroll 开发小记

背景:一次左滑加载更多的的交互开发

填坑开始

在最开始时,我得到了一个提示,左滑加载更多类似下拉刷新。想了想,好家伙,不就是把下拉刷新横过来嘛,碰巧下拉刷新还是前几天新增的一个组件,这回可以借鉴借鉴了 😍。OK 开干!

下拉刷新组件的设计

在查看组件的源码后,发现下拉刷新组件的设计其实比较简单。这里使用了 @use-gesture/react 用在手势上的绑定,react-spring 用作动画的实现。下面就简单介绍下其设计思路。

首先抛出几个问题

  • 什么时候触发刷新 或者什么时候调用手势?
  • scroll 容器滚动时与手势冲突。
  • 下拉的阈值、回弹动画
  1. 下拉刷新组件在设计时,采用的是浏览器原生滚动加上自定义用户手势事件。这样我们很容易判断什么时候触发手势事件了。其答案是:判断 dom 节点的 scrollTop,当 scrollTop 为 0 时,说明已经到顶了,然后在往下拉时,就开始触发手势,当手势下拉的距离超过某个阈值时,即变为了可刷新的状态,松手后,直接触发下拉回调。

  2. 从问题 1 的答案我们就可以很合理地规避原生滚动与手势下拉的冲突,及 scrollTop 不为 0 时,不会触发手势事件。

  3. 通过 use-gesture/react 中的 rubberbandIfOutOfBounds 函数创建一个弹簧效果,回弹动画呢,这个组件采用的是设置 loading 的 height 来实现,虽然可以,但我理解这种动态高度不是太适合这种滚动场景。因此后面经过各种实验(踩坑)后,丢弃了这种改变高度(宽度)的方式展示 loading。

大概的一个框架图

img_1

横滑实践

横滑多简单呢,把竖着的横过来就是了 😊。哈哈,确实是这样的。

Version 1

基本套路:

  • overflow:hidden
  • transform:translate3d
    基于以上套路,第一版没有采用浏览器的原生滚动,然后全程触发手势事件,通过手势事件控制 react-spring 的动画参数,实现模拟滚动。显然,模拟滚动的效果不是太好,其原因在于滚动速率变化、滚动惯性等比较难控制(实际原因:🥬 🐶)。
    下面来看一下初版效果:

img_2

目测效果还行,但是在真机调试上就比较拉胯了,在真机上,实际移动的距离是手指一动的距离,所以是非常的慢并且每一次滚动的距离、速度这些比较受限。

Version 2

参考 picker 组件,做一个滚动惯性。这种滚动对应的是每一次移动,终点位置都是一个整数位置(最终移动坐标是: index * itemWidth 或者 itemHeight)。

Version 3

思路:原生滚动结合手势,这款设计比较合理,原生滚动改善了速度问题,横向长列表在滚动时,只有到滚动到最右边时才触发整体容器的移动,然后露出 load。
注意:原生滚动采用 overflow:auto。在滚动到最右边时,触发手势,需要设置 overflow:hidden,不然就会发生滚动重叠(原生的在滚动、手势也在移动)。

img_3

看似可用了,然而 ios 有个坑点,原生滚动具有惯性回弹,所以,当你拇指快速左滑时,会出现一个滚动回弹。这个回弹不会将 load 露出来,反而露出的是一个白底。

能用待改善

如标题所说,最终版只是一个能用的版本。各种原因,选择将 load 放在了原生 scroll 里面了(里外差别不大 😅)。

img_3

待优化的点

  • 原生滚动不能有回弹效果,如果需要增加回弹效果,需要手动模拟滚动,然后再添加回弹。(ios特定的边界弹簧效果不能禁止)
  • 边界 drag 不流畅,有待改进。
-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道