| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> 匠心打造多tab自动吸顶下的多滚动容器(详细) -> 正文阅读 |
|
[系统运维]匠心打造多tab自动吸顶下的多滚动容器(详细) |
背景不知道什么时候开始,一种tab自动吸顶下的多容器嵌套滚动浏览交互方式逐渐风靡在各大电商APP(美团、京东、拼多多等)。 这种相对复杂交互的滚动容器一般都在APP首页容易看到,实现的技术栈是客户端,h5下的实现案例比较少见,目前就只看到闲鱼跟拼多多有基于h5技术实现案例。个人猜测原因主要有两点: 1. 对于多容器嵌套滚动缺乏原生能力支持,实现成本较大; 2. 自行实现多容器嵌套滚动能力流畅性不达标,毕竟h5是基于webview来进行渲染,在滚动浏览阶段稍有计算必然会导致帧率下降。 效果与特征但这样的滑动浏览交互在我们h5场景也同样存在强烈诉求,基于这篇文章,我给大家介绍下我们前端团队基于h5打造的多容器嵌套滚动浏览的实现方案。在介绍之前我们先来看下我们的体验效果: 从上面的效果我总结一下,一个既要满足视觉交互又要满足业务复杂诉求的多tab滚动容器需要具备以下特征: 1.外层滚动容器与tab容器滚动是一体化,滚动过渡要自然 2.tabbar在滚动至顶时需自动吸顶 3.不同tab容器之间支持横滑切换浏览操作 4.不同tab容器的滚动浏览是隔离的,需要保持各自的浏览位置 5.不同tab容器可以承载着无限列表内容 常见方案滚动偏移传递方式从iOS客户端同学那学习到一种方案是通过最顶层的一个不可见滚动容器(S0)来传递滚动偏移量,而真正内容承载的容器使用的是传统的外滚动容器(S1)嵌套多个子滚动容器(S2-x)方式,大致原理可以参考下图:? 大致思路如下: 1.S0同步S1与S2-x的滚动偏移总和,S0统一接收来自用户的滚动行为 2.在tabbar触顶之前,S0的滚动偏移传递给S1 3.在tabbar触顶之后,S0的滚动偏移传递给S2-x 4.在tab子容器横滑之后,根据S2-x的滚动偏移来重置最顶层S0的滚动偏移计数 注:S2-x代表当前的子滚动容器 上面方案有以下优势: 1.多子滚动容器相互之间天然隔离,天然实现各tab容器的浏览记录隔离特性; 2.得益于最顶层的不可见滚动容器来接收统一的滚动交互,可以将滚动惯性传递下去,这点很重要,我们都知道单纯的两个嵌套滚动容器,滚动惯性是不能够从父容器传递到子容器的。 但上面的方案是否适合h5技术栈呢?顶层滚动行为需要监听,滚动时需要实时传递滚动偏移,真正承载内容的滚动容器不再是复用原生滚动能力,而且是由js计算驱动滚动。然而h5技术栈运行在webview中,属于APP系统下的一个子系统,性能相对敏感。从以往经验,容器滚动时的任何js执行都有可能导致掉帧,我们要打造滚动极致流畅只能是完全贴合h5原生的滚动,做到滚动阶段无监听、无计算。 注:Android端的NestedScrollingParent虽然是原生控件,但思路是与上面方案是大体一致的,都是父滚动事件分发的思路。 闲鱼h5方案为了很好解决特征1,我们的方案是基于独一的滚动容器,并且直接复用滚动容器的默认滚动行为,不做滚动偏移传递或者滚动时的计算。从下图结构看出,我们唯一的滚动容器是S0,它承载所有需要展示的内容,包括多tab模块与其他模块,多tab模块中由各自子容器(C0~3)承载对应的内容,子容器不再是滚动容器。初始化阶段记录各子容器对应的外层滚动偏移值(scroll_0~3 = 0),并根据当前tab子容器C1 初始状态上下滚动状态S0上下滚动时,为了实现特征2,我们的tabbar吸顶功能采用position:sticky来实现,使用sticky最大的收益就是吸顶衔接效果好,滚动过程无额外滚动监听计算。从sticky支持的程度来看(iOS9,Android 5.0)刚好能我们移动侧的最低兼容机型。 横滑开始在解决特质4时,我们在横滑开始切换时tab子容器时需做两件事, 1.根据多tab模块当前的距离顶部偏移量offset_1来设置其余非可见区的子容器(C0/C2/C3)顶部偏移值,以保切换过程的独立浏览位置正确展示 2.记录此时外层滚动容器的滚动偏移值n1,并记录为scroll_1 = n1 以上操作会在横滑视觉效果之前完成,保证横滑过程中能正确看到下一子容器的正确浏览位置。 横滑结束当横滑动作结束后,我们做了三件事 1.恢复当前子容器C2的顶部偏移 2.使用当前子容器记录的滚动偏移scroll_2来重新计算滚动容器S0的滚动偏移量 3.重置掉其他非可见区的子容器顶部偏移 横滑至有浏览记录的tab容器在当前tab容器为C2子容器时继续进行上下滚动浏览,当外层容器S0滚动值为n2时(此时C2容器距离顶部的偏移为offset_2);再次进行右横滑交互,此时需要操作基本与第二步一致,但是由于C1已经存在滚动记录,所以需对C1进行另外的计算方式:外层滚动偏移n2 减去 C1记录的滚动偏移scroll_1 (n1)。 以上方案就能很好的完成开始总结的5个特征,并且在h5场景最大好处有两方面: 1.各个tab容器中的内容在滚动浏览过程中始终出自唯一的滚动容器,不会存在嵌套滚动中的滚动惯性无法传递或者传递过程的损耗; 2.主容器滚动过程完全依赖原生的滚动能力,没有任何的js计算,给16.6ms留足了时间。 至此,所有大致的思路已经完成,但还有些边界情况仍需要我们打磨。 匠心打磨iOS下的translate3d闪屏问题在水平方向横滑浏览时,为了能达到最好的流畅度,我们采用的是translate3d,实现结构如下; 当translate3d作用于在一块较大图层时是会偶现闪屏问题,猜测与合成图层(Compositing Layer)的实现有关系,在合成渲染加速架构中使用了translate3d的渲染图层会被提升为合成图层,每个合成图层会拥有自己独立的纹理缓存与相应的管理机制;但即便是拥有独立的纹理缓存管理,也同样受限于底层OpenGL最大纹理尺寸大小(2000 * 2000像素点)。而网上常规的解法为每个滑块添加-webkit-translate3d: (0px, 0, 0)其实就是为了将一张大的合成图层拆成各个小的合成图层。 中间父节点的overflow:hidden导致position:sticky吸附失效问题随着业务的使用,交互场景越来越多样化,每个tab容器中开始出现子tabbar的交互,子tabbar也希望能sticky到主tabbar底部,这时候我们业务同学发现直接将子tabbar的吸附到主tabbar底部时发现不生效,定位后发现是由于tab容器设置了overflow:hidden属性,这个问题很久前就有过关于标准的争论,大概的意思是sticky节点是以最近一个拥有滚动机制的父节点来固定,怎么定义拥有滚动机制呢?overflow不等于visible时。但至于为什么overflow:hidden也算拥有滚动机制呢,猜测应该是只要是涉及到内容溢出就算吧,毕竟可以通过js来实现scroll。
我们之所以要给某些容器设置overflow:hidden主要原因是在不同tab容器内容高度是不一致的,为保证当前tab正确的滚动高度,我们需要借助overflow:hidden来裁剪掉相比当前tab容器长度要长的其余容器,大致如下图: 子tab吸顶问题与overflow:hidden之间没有什么好的解法,我们最终选择的是绕开它两同时的时机。 横滑开始时:所有tab容器取消overflow:hidden,这样可以保证横滑过程中看到的是正常吸顶的? 横滑结束时:当前可见tab容器不需要设置,其他tab容器设置overflow:hidden 其他除此之外,我们还解决了好多更细的问题,比如 ?Android部分机型(基于Chrome 69及之前的内核)出现侧滑问题,父容器overflow:hidden无法防止孙子节点超宽内容左右拖拽 ?Android中低端机型Intersection Observer捕获频率不足的问题 ?多tab之间跳跃切换时如何确保其他中间tab不被触发加载问题 未来规划在方案分析过程中,我们也意识到了合成图层带来的GPU纹理缓存压力,前期考虑到webkit内核本身也会根据实际情况回收,并不会无边界开销;但对于我们来说在更长的列表中节点回收是不可逃避的话题,等待我们去解决的问题还很多,如何做到不定高回收重建?如何在不影响滚动性能的同时设计高性能回收与重建?低系统版本应该如何考虑?等等 相关阅读https://trac.webkit.org/wiki/CoordinatedGraphicsSystem https://github.com/w3c/csswg-drafts/issues/865 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 15:36:39- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |