From 5d21cc7d655e3dd91666a48ddb358e20552d27ea Mon Sep 17 00:00:00 2001 From: lanterngamescn Date: Sat, 27 Jun 2026 00:14:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20H5=20canvas=20=E5=8A=A8?= =?UTF-8?q?=E7=94=BB"=E5=AE=9A=E6=A0=BC=E4=B8=8D=E4=B8=8A=E5=B1=8F"?= =?UTF-8?q?=EF=BC=9A=E6=B3=A8=E5=85=A5=E5=90=88=E6=88=90=E4=BF=9D=E6=B4=BB?= =?UTF-8?q?=EF=BC=88=E6=8C=89=E9=92=AE=E6=8C=89=E4=B8=8B=E7=BC=A9=E6=94=BE?= =?UTF-8?q?=E7=AD=89=E6=81=A2=E5=A4=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因(真机定位):ArkWeb 默认 ASYNC 渲染下,H5 用 requestAnimationFrame 逐帧重绘 (JS 在跑、像素在变,rAF/时钟/引擎循环/CSS 经探针全部证实正常),但 ArkWeb 判定"组件内容未变" 不再产出新合成帧 → canvas 更新不上屏,表现为按钮按下缩放等 canvas 动画定格;连上 DevTools 会强制持续合成,故"调试时正常、真机直接点不动"。SYNC_RENDER 无效。 修法(H5 零改动,原生注入,符合铁律):onPageEnd 注入一个不可见(opacity .02/1px/pointer-events:none)、 独立合成层(will-change:transform)元素,每帧微动其 transform,强制 ArkWeb 持续产出合成帧, 把 canvas 一并刷上屏(等效 DevTools)。rAF 在页面不可见/后台自动暂停,仅前台活跃期有开销。 真机验证:注入后"无自带 nudge 的测试画布"纯靠该保活即可逐帧上屏(连拍 5 帧 md5 全不同)。 Co-Authored-By: Claude Opus 4.8 (1M context) --- entry/src/main/ets/web/WebSlot.ets | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/entry/src/main/ets/web/WebSlot.ets b/entry/src/main/ets/web/WebSlot.ets index f9b527d..dcfb9bf 100644 --- a/entry/src/main/ets/web/WebSlot.ets +++ b/entry/src/main/ets/web/WebSlot.ets @@ -100,6 +100,30 @@ export class WebSlot { onPageEnd(): void { this.bridgeCtrl?.onPageEnd(); + this.injectCompositingKeepAlive(); + } + + /** + * 🔴 合成保活(修复 H5 内 canvas 动画"定格不上屏")。 + * 现象:ArkWeb 默认 ASYNC 渲染下,H5 用 requestAnimationFrame 逐帧重绘 (JS 在跑、 + * 像素在变),但 ArkWeb 判定"组件内容未变"不再产出新合成帧,于是 canvas 更新不上屏—— + * 表现为按钮按下缩放等 canvas 动画定格(连上 DevTools 会强制持续合成,故调试时正常)。 + * 修法(H5 零改动,原生注入):插入一个不可见、独立合成层(will-change:transform)的 1px 元素, + * 每帧微动其 transform,强制 ArkWeb 持续产出合成帧,把 canvas 一并刷上屏(等效 DevTools 效果)。 + * rAF 在页面不可见/后台时自动暂停,故仅前台活跃期有开销。每次 onPageEnd 注入,window.__arkKA 幂等。 + */ + private injectCompositingKeepAlive(): void { + const script: string = + "(function(){if(window.__arkKA)return;window.__arkKA=1;" + + "var d=document.createElement('div');" + + "d.style.cssText='position:fixed;left:0;top:0;width:1px;height:1px;opacity:0.02;pointer-events:none;z-index:2147483647;will-change:transform';" + + "function add(){var r=document.body||document.documentElement;if(!r){setTimeout(add,50);return;}r.appendChild(d);" + + "var n=0;(function t(){n^=1;d.style.transform='translateZ(0) translateX('+n+'px)';requestAnimationFrame(t);})();}add();})();"; + try { + this.controller.runJavaScript(script); + } catch (e) { + WebSlot.log.w(`[${this.role}] keep-alive inject failed: ${(e as BusinessError).message}`); + } } /** 渲染子进程退出(崩溃/被杀/OOM):重载本 Web 恢复,防白屏(T-M5-04)。