Skip to content

Electron BrowserView层级管理优化:基于位移的创新方案

背景

为了提高直播间的稳定性和用户体验,我们在 Electron 客户端采用了多容器(多 BV,Browser View)底层架构。这些容器分别用于不同的功能模块,如直播间、互动题、通用互动、系统 UI 等等,每个模块都有独立的容器。这种多容器架构能更好地分离关注点,提高系统的可维护性和扩展性。然而,这种架构也带来了一些新的挑战,尤其是在容器层级管理方面。

在传统的布局设计中,CSS 可以通过 z-index 来轻量地调整 DOM 元素的层级,但在多容器架构中,由于每个容器在 Electron 中都有独立的渲染进程和视图,它们无法通过简单的 z-index 机制来控制层级。此时,Electron 提供的 setTopBrowserView 方法成为了调整容器层级的主要手段。然而,频繁调用 setTopBrowserView 来调整容器的层级会带来显著的性能损耗,尤其是在一些需要频繁调整层级的场景中。

Electron 中 setTopBrowserView 成本消耗

setTopBrowserView 是 Electron 提供的用于调整浏览器视图层级的方法。通过调用该方法,可以将指定的容器设置为最上层,确保其能够显示在其他容器之上。然而,这种方法存在显著的缺点:

  1. 性能损耗BrowserView 的层级调整可能涉及底层 GPU 渲染的重新排序,尤其是在多容器架构中,当多个视图的层级频繁变动时,GPU 的渲染操作可能会变得更为繁重,导致渲染延迟和性能下降。
  2. 事件延迟:由于 setTopBrowserView 调用是基于事件驱动的,且涉及到底层的渲染进程,频繁的调用可能会引入操作延迟,尤其在容器数量较多或者交互场景较复杂时,延迟表现尤为明显。
  3. 层级调整的复杂性:在多容器架构下,管理层级的操作变得尤为复杂。例如,如果我们需要将容器 d 调整到底部并保持容器 abc 的顺序不变,必须依次调用 setTopabc 的层级调整为顶部,然后再调整 d。这种操作不仅繁琐,而且容易出现错误,导致层级顺序的混乱和视图的不稳定。

层级管理仅依赖 setTopBrowserView 的弊端

在传统的基于 setTopBrowserView 的层级调整方案中,每次调整都需要重复执行一系列的 setTop 操作,这样会导致以下问题:

  1. 不便于管理:每次层级调整都涉及到多个容器的逐一操作,这使得管理变得非常困难。特别是在容器数量较多时,频繁的层级调整可能导致操作失误或遗漏,最终影响系统的稳定性。
  2. 重复操作的延迟:在直播间的实时场景中,信令时机的把握至关重要。频繁的层级调整会导致多个容器的状态和层级出现不同步的情况,增加了事件的延迟,影响了用户体验。
  3. 容器切换错乱:多次重复的层级调整可能导致容器顺序错乱,无法保证容器的展示顺序与预期一致,尤其是在复杂的交互场景下,可能会发生不可预料的 UI 错乱。

创新思维 - 层级调整为位移

为了解决上述问题,我们提出了将层级调整从传统的 setTopBrowserView 调整方式,转变为基于位移(Bounding Box 更新)的方式。这种思路的核心在于,将容器的层级结构固定不变,仅通过更新容器的可视区域来控制其显示顺序,从而避免了频繁的 setTop 操作。

具体实现

  1. 固定层级结构:我们不再依赖于 setTopBrowserView 进行频繁的层级调整,而是将容器的显示顺序通过位移的方式进行管理。每个容器在初始化时,都会根据其功能和显示顺序被固定在一定的层级位置。
  2. 通过 Bounding Box 更新位置:当需要展示某个容器时,只需通过 updateBvBounding 方法更新容器的显示区域(Bounding Box)。这一操作仅仅是更新容器的位置和可视区域,无需修改容器的层级,从而减少了性能损耗。
  3. 无需频繁调整层级:由于容器的层级关系已经固定,当容器需要显示时,只需将其位移到可视区域内即可。这种方式比传统的 setTop 调整要高效得多,且避免了容器层级混乱的风险。

优势

  1. 提升性能:通过减少 setTopBrowserView 的调用,避免了频繁的渲染更新,显著提高了性能。特别是在直播过程中频繁的容器切换中,新的方案能够保证更平滑的用户体验。
  2. 简化管理:由于层级结构是固定的,我们只需要关注容器的位置和可视区域,而不再需要频繁调整容器的层级顺序。这使得容器的管理变得更加简洁高效,减少了出错的机会。
  3. 减少延迟:通过位移方式来管理容器的显示顺序,减少了由于事件驱动的层级调整带来的延迟,从而提高了实时互动场景中的响应速度。
  4. 增强稳定性:固定层级结构和位置更新的方案,避免了频繁的层级切换和容器状态不一致的问题,使得整个直播系统在高负载和复杂场景下表现更加稳定。

问题

通过测试发现,如果直接将容器完全移出可视区域(即将容器的位置调整到完全不可见的区域),某些容器的事件响应会受到影响,导致无法正常执行。这是因为 Electron 或 Web 环境下,某些事件(如点击、焦点等)会受到视图的可见性和位置的影响。因此,单纯地将容器完全移出视图并不完全符合我们的需求。

解决方案 - 位移至用户看不到的区域

基于上述问题,我们提出了将容器移到可视区外,但保持容器的可见区域部分在可视范围内(例如只暴露 1px 的区域)。这样做的目的是:

  1. 保持事件可执行性:通过将容器的 1px 露出在屏幕的左、右或下角,即使容器几乎不可见,它仍然能够接收事件。这确保了容器在被移出主视图区域时,其内部的事件(如点击、交互等)能够继续触发,从而避免因容器完全不可见而导致的事件丢失问题。
  2. 避免视觉干扰:容器只有 1px 的可见区域,用户几乎无法感知容器的存在。这保证了 UI 的清爽和无干扰,同时能够确保容器的事件和行为仍然有效。
  3. 简化可视区管理:将容器移动到用户看不见的位置(如左、右或下角)而不是完全移出可视区域,避免了因容器完全消失而导致的状态更新或渲染问题,进一步简化了多容器架构的管理和调度。

总结

通过创新性地将传统的层级管理方式转变为基于位移的方式,我们能够有效地提高多容器架构下的性能、简化容器的管理,并降低因频繁层级调整带来的延迟和错乱问题。相比于传统的 setTopBrowserView 方法,位移方案在当前场景下无疑是更加高效且可控的解决方案,为直播间的稳定性和用户体验提供了坚实的保障

在 MIT 许可下发布