Android同层渲染技术_Android同层渲染技术


效果展示

先看Demo视频,对比App内常规的H5播放体验和使用同层渲染视频组件后的H5页面播放体验:

常规H5 <video/>播放体验


Android同层渲染技术_Android同层渲染技术_02

常规H5 <video/>播放体验https://www.zhihu.com/video/1247184143089549312

使用同层渲染视频组件后H5页面的播放体验


Android同层渲染技术_不挂载 组件渲染_03

使用同层渲染视频组件播放体验https://www.zhihu.com/video/1247184451903643648

使用同层渲染视频组件后H5页面播放器手势交互


Android同层渲染技术_不挂载 组件渲染_04

同层渲染视频组件播放器手势交互https://www.zhihu.com/video/1247194274044391424

众所周知,H5 <video/> 标签的播放体验有诸多限制:iPhone设备上不能自动播放,全屏时无法横屏播放,退出全屏时播放自动暂停了,能响应的手势有限。 和原生端实现的播放器相比,交互和体验确差距很大。

小程序在刚问世时,就提供了原生组件,针对强交互场景,如视频播放,文本输入框、地图组件等,原生组件为小程序带来了更丰富的特性和更高的性能。既然微信小程序框架可以通过同层渲染原生组件,提升小程序页面的交互体验,那作为H5容器的开发者,可否让普通H5页面像小程序页面一样,也能具有使用原生组件的能力呢?

这就引入了本文的主题:支持原生组件同层渲染的H5容器。

技术实现

微信团队公开了小程序同层渲染原理:《微信小程序同层渲染原理剖析》,iOS端主要原理如下:

当把一个 DOM 节点的 CSS 属性设置为 overflow: scroll 之后,WKWebView 会为其生成一个 WKChildScrollView,与 DOM 节点存在映射关系,这是一个原生的 UIScrollView的子类,也就是说 WKWebView 里的滚动实际上是由真正的原生滚动组件来承载的。小程序 iOS 端的「同层渲染」也正是基于 WKChildScrollView 实现的,原生组件在 attached 之后会直接挂载到预先创建好的 WKChildScrollView 容器下,大致的流程如下:

1. 创建一个 DOM 节点并设置其 CSS 属性为 overflow: scroll ;

2. 通知客户端查找到该 DOM 节点对应的原生 WKChildScrollView 组件

3. 将原生组件挂载到该 WKChildScrollView 节点上作为其子 View。

其中第1步是JS做的,第2步是小程序webview容器自行处理,第3步是 JS 和 webview 容器协作完成。

// TODO 未完待续

一些关键细节:

  • 捕获WKChildScrollView实例,并和网页 DomTree 中具体设置了overflow:sroll;属性的DOM节点一一关联
  • 让原生播放器 PlayerView 接收Touch事件并解决与WKWebView 上的手势冲突问题
  • 原生播放器PlayerView 生命周期管理

Demo 运行时 HTMLDOMTree


Android同层渲染技术_Android同层渲染技术_05


Demo 运行时 iOSViewHierarchy


Android同层渲染技术_Android同层渲染技术_06


产品化开发需要按照 Web Component 规范将同层渲染播放器组件暴露给JS 同学使用。如下图所示百度小程序运行时DOM 树截图,虽然小程序开发者使用的仍然是<video/>标签,但最终生成的DOM树中使用的是自定义标签<swan-video>节点:


Android同层渲染技术_不挂载 组件渲染_07


从上图也可以看出,小程序组件其实都是使用Web Component封装的。所以给H5页面开发同学提供 同层渲染Video组件时,将会提供一个新的自定义标签。

除了视频播放器,H5 页面的 input/textarea 组件交互体验也很差,使用同层渲染来技术桥接原生UITextField/UITextView 组件将会明显提升H5页面上用户和软键盘交互体验。