在开放网络上,Canvas 与 WebGL 支撑着流畅的 K 线图、实时盘口与 3D 持仓可视化。在 WebView 里,它们会卡顿或失效。Android WebView 除非在窗口级开启硬件加速,否则回退到软件渲染——没开时 canvas.getContext('webgl') 直接返回 null。iOS 在内存压力下会悄悄杀掉 WebKit GPU 进程,且不触发 webglcontextlost,于是画面变黑、而 JavaScript 还在跑。宿主自有 runtime 桥接原生渲染——图表与可视化在每个引擎上都保持 60fps。
Android:默认软件渲染,WebGL 依赖窗口加速
Android WebView 支持两种模式:使用 GPU 的硬件层(WebGL 所必需)和使用 CPU 的软件层。默认层类型是 LAYER_TYPE_NONE,关键在于 WebView 继承窗口的硬件加速状态。如果 Activity 或窗口关闭了加速(Unity/游戏/嵌入式场景很常见),WebView 会静默回退到 CPU 光栅化,getContext('webgl2') / getContext('webgl') 返回 null。修复不只是在 manifest 里写 android:hardwareAccelerated="true";WebView 自身的窗口必须加速,setLayerType(LAYER_TYPE_HARDWARE, null) 才是显式兜底。即便开启了,后台切换时的 GPU 上下文丢失也强制要求显式重绘,否则就是黑屏。
iOS:GPU 进程被杀,且不会通知你
在 WKWebView 中,渲染运行在独立的 WebKit GPU 进程里。内存压力下 iOS 会杀掉该进程——而且它不会触发 webglcontextlost。应用还在前台,JavaScript 还在跑,HUD 还活着,图表却是黑的。iOS 16+ 还收紧了 WebGL 限制:跨域资源(CDN 上的着色器、纹理)默认被 limitsNavigationsToAppBoundDomains = YES 拦截,强制降级到 CPU 渲染,出现肉眼可见的掉帧。实际结果是:在 Safari 里 60fps 的 Three.js / PixiJS 场景,在 WebView 里要么卡成幻灯片,要么黑屏。
渲染卡顿会带来什么
- K 线与深度图卡顿。 券商蜡烛图、盘口、tick 行情掉帧,交易者读到的是滞后或陈旧的价格。
- 3D 持仓与组合冻结。 持仓、风险曲面、地图等 WebGL 可视化在滚动或内存压力下变黑。
- 耗电与发热飙升。 CPU 软件光栅化 Canvas/WebGL 既耗电又烫手。
- "我桌面上是好的"陷阱。 这些失败只在真机上出现,桌面 Chrome 永远复现不了。
runtime 解法
宿主自有 runtime 桥接渲染层。对重型可视化,宿主提供原生图表 / GPU 表面,由页面通过 runtime.renderChart() 或原生视图驱动;对 Canvas/WebGL,则保证加速上下文并处理上下文丢失恢复。页面保留声明式图表代码,runtime 保证 GPU。一次集成,每个引擎通用,最终拿到的是流畅的一帧。
| 维度 | WebView | 宿主自有 runtime |
|---|---|---|
| Android WebGL | 软件回退;窗口未加速时 getContext('webgl') 为 null | 保证硬件层 |
| iOS GPU | 进程被杀,无 webglcontextlost | 原生表面 + 恢复 |
| 跨域资源 | 被 app-bound 域名拦截 | 打包 / 原生加载 |
| 帧率 | 掉帧、黑屏 | 60fps 目标 |
| 上下文丢失 | 静默黑屏 | 可观测、可恢复 |
| 一致性 | 因引擎而异 | 统一 |
原生应用能在每台设备上用 GPU 渲染图表;裸 WebView 几乎在每台设备上都不行。runtime 给页面一条渲染路径——以及一帧可以信赖的画面。
参考来源
- Android WebView — 硬件加速与层类型 — WebView 渲染依赖窗口的硬件加速状态;软件回退会让 WebGL 失效。
- Android WebSettings — setLayerType / 分层渲染 —
LAYER_TYPE_HARDWARE是为 WebGL 启用 GPU 合成的显式路径。 - Apple Developer — WKWebView — WKWebView 在独立进程中运行 WebKit;iOS 在内存压力下管理 GPU 进程。
- DEV Community — 向 iOS 发布 Three.js 游戏(GPU 进程死亡) — iOS 杀掉 WKWebView 的 GPU 进程且不触发
webglcontextlost;软件渲染回退是静默的。 - CSDN — WebView Three.js 性能 / 硬件加速 — Android WebView 默认软件渲染;WebGL 需要
LAYER_TYPE_HARDWARE以避免上下文为 null。