资讯专栏INFORMATION COLUMN

移动端模拟滚动

douzifly / 530人阅读

摘要:背景由于移动端原生滚动的局限性以及兼容性,部分特定场景的需求无法满足。示例模拟滚动知识点通过移动端的系列事件触发模拟滚动,获取手指滑动的偏移量,进而改变来进行位置偏移。

背景

由于移动端原生滚动的局限性以及兼容性,部分特定场景的需求无法满足。例如,笔者最近就接了一个需求:整个页面分为三块,每块内容的高度不等(但都超过一屏),要求滚动到内容的临界点有一个停顿的效果,下拉可以看到下一块的部分内容,满足条件则滑到下一块内容。这种场景下,原生的滚动根本无法支持。因此,本文的主角就亮相了:模拟滚动,即尽可能的模拟原生滚动,但是又提供了一些扩展,满足复杂场景的需求。

本文将从模拟滚动需要实现的功能、技术分析和方案来进行阐述,通读本文,读者将对模拟滚动的常见功能和技术要点有一定了解。

示例:模拟滚动

知识点

通过移动端的touch系列事件触发模拟滚动,获取手指滑动的偏移量,进而改变translateY来进行位置偏移。

滚动容器

滚动容器拥有高度,滚动区域的高度大于滚动容器,在滚动时,我们对滚动区域进行偏移,以达到滚动的视觉效果。

通过滚动区域的高度可以通过offsetHeight获取,但是在以下情况下会远远小于实际高度。

内联样式:在DOM节点生成时,样式还未渲染完成,此时获得的高度是默认样式的高度,待样式渲染完成后,高度可能会有变化

图片高度:img节点的高度开始是0,在图片加载完成时,才会等于图片高度,因此这里也会存在误差

惯性滚动

我们知道,为了让滚动更加流畅,原生的滚动会有一个惯性滚动的效果,即手指快速滑动松开后,滚动区域会继续滚动一段距离后停止。

为了实现这个功能,我们需求知道手指滑动的速度,根据比率计算目标滚动位置,然后驱动滚动,让其到达目标位置。

这里笔者尝试了两种方案:

通过requestAnimationFrame不断进行偏移,直到到达目标位置

使用transition进行过渡,设置动画曲线让其到达目标位置

笔者对比了两种方案,最终选择了方案2,原因是transition过渡会更加的流畅,而requestAnimationFrame会有略微的卡顿,但是transition过渡,我们实时触发滚动事件时,不好拿到其当前的位置,查阅了一些资料,笔者最终找到了解决方法,即getComputedStyle,这个API可以拿到当前页面渲染的实时样式,也就是说,哪怕它处于过渡动画中,我们可以实时拿到它的真实位置。

边界回弹

当滚动超出边界时,通常我们还可以让其继续滚动,但是这时候会设置阻碍,即滚动速度慢下来,当滚动停止时,我们再将其拽回到边界线。我们可以通过监听transitionend事件来判断惯性滚动停止,这里的技术点不做过多分析,感兴趣可以在文末中的源码找答案。

默认行为

通常情况下,我们需要阻止浏览器的默认行为(如滚动),但是这样也会误杀一些我们需要的默认行为(如超链接跳转、输入框聚焦)。

解决方法很简单,在touchstart触发时,我们判断一下目标节点是否需要阻止默认行为,比如说tagName=INPUT,我们不阻止默认行为。

点击事件

默认行为被阻止,绑定在子节点上的点击事件就无法触发了,因此这里我们需要判断一下是否需要触发点击事件。可以通过touch系列事件模拟点击行为,然后通过document.createEvent("Event")来主动触发click事件。

滚动指示器

在滚动区域中,通常在右侧会有一个指示器,用于查看当前在整个内容区块的大概位置。

为了方便使用,笔者注册了一系列的钩子,方便使用者调用,scroll钩子就是其中之一,在滚动的时候它会实时触发,在这里就派上用场了。我们通过scroll钩子改变指示器的位置,唯独要注意的是滚动超出边界时,指示器会变短然后恢复。

@axe/scroller

基于以上知识点和技术分析,笔者写了一个模拟滚动js库(无任何依赖):https://github.com/ansenhuang/axe/blob/master/packages/scroller/README.md

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97644.html

相关文章

  • 移动滚动研究

    摘要:还会有一个性能上的问题就是当页面的列表过长,元素过多时,在模拟滚动,下拉刷新这段时间内,页面也会有卡顿现象,这里采取了一个优化策略即列表较长时数量较多时,在触发下拉刷新的时机时将页面视窗之外的元素隐藏或者存放在里面。 移动web滚动问题 在移动端如果使用局部滚动,意思就是我们的滚动在一个固定宽高的div内触发,将该div设置成overflow:scroll/auto;来形成div内部的...

    ghnor 评论0 收藏0
  • Issues with position fixed & scroll(移动 fixed

    摘要:同时,请在其他移动端浏览器也这么处理,不要只对苹果做这些处理。苹果对于虎头蛇尾的做法真让人头疼,这作风跟巨硬真像。 转载请注明英文原文及译文出处 原文地址:Issues with position fixed & scrolling on iOS 原文作者:Remy Sharp译文地址:移动端 fixed 和 scroll 问题 译文作者:鎏金圣手火麒麟 最近在做iOS端的H5页面...

    Jiavan 评论0 收藏0
  • Issues with position fixed & scroll(移动 fixed

    摘要:同时,请在其他移动端浏览器也这么处理,不要只对苹果做这些处理。苹果对于虎头蛇尾的做法真让人头疼,这作风跟巨硬真像。 转载请注明英文原文及译文出处 原文地址:Issues with position fixed & scrolling on iOS 原文作者:Remy Sharp译文地址:移动端 fixed 和 scroll 问题 译文作者:鎏金圣手火麒麟 最近在做iOS端的H5页面...

    ZoomQuiet 评论0 收藏0
  • 动画历程之滚动的坑

    摘要:很多时候我们在上做动画一般都是选择滚动事件来触发。而在移动端的浏览器或中,滚动事件的触发频率也是不同的。在中在视图的滚动过程中,事件不会被触发在滚动结束后,才会触发和不受此影响。但是滚动触发事件与滚动距离以及完成的时间有关。 很多时候我们在web上做动画一般都是选择滚动事件来触发。因为动画需要判断是否处于视口内,或者是否到达某个临界点。而滚动在不同的浏览器中,不同操作系统中的实现都有不...

    asce1885 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<