html2canvas 1.4.1 在 iOS Safari 中生成图片卡住的问题排查与修复

html2canvas 1.4.1 在 iOS Safari 中生成图片卡住的问题排查与修复

问题现象

在 iOS Safari / 移动端 vConsole 环境中,使用 html2canvas 1.4.1 时无法成功生成图片。

最初看到的报错类似:

text 复制代码
TypeError: undefined is not a function

(near '...t.match(...)...')

同时 html2canvas 日志停在:

text 复制代码
Starting document clone...

之后没有进入 resolved,也没有正常输出 canvas。

最小复现

为了判断是脚本问题还是业务 DOM 问题,先做了一个最小 DOM 测试:

js 复制代码
function testHtml2canvasCore(scriptUrl) {

    scriptUrl = scriptUrl || "https://cdn.staticfile.org/html2canvas/1.4.1/html2canvas.min.js";

  


    $.getScript(scriptUrl + "?v=iframefix").done(function () {

        var demo = document.createElement("div");

        demo.id = "html2canvasCoreDemo";

        demo.style.cssText = [

            "position:fixed",

            "left:10px",

            "top:10px",

            "width:120px",

            "height:60px",

            "background:#fff",

            "color:#111",

            "font-size:14px",

            "z-index:999999"

        ].join(";");

        demo.innerHTML = "core demo";

        document.body.appendChild(demo);

  


        html2canvas(demo, {

            scale: 1,

            useCORS: true,

            logging: true

        }).then(function (canvas) {

            console.log("core demo ok", canvas.width, canvas.height);

        }).catch(function (err) {

            console.error("core demo error", err);

        });

    });

}

测试结果:

  • 使用 1.4.1:最小 DOM 也卡住。

这说明问题第一层不在业务 DOM,而在 html2canvas 1.4.1 自身的 document clone / iframe 流程。

根因定位

html2canvas 1.4.1 在生成图片前会 clone 当前 document 到一个隐藏 iframe 中,然后等待 iframe 加载完成。

相关的 minified 代码原本类似:

js 复制代码
In=function(B){

    return new Promise(function(e,A){

        var t=B.contentWindow;

        if(!t)return A("No window assigned for iframe");

        var r=t.document;

        t.onload=B.onload=function(){

            t.onload=B.onload=null;

            var A=setInterval(function(){

                0<r.body.childNodes.length&&"complete"===r.readyState&&(clearInterval(A),e(B))

            },50)

        }

    })

}

关键问题在这里:

js 复制代码
t.onload = B.onload = function () { ... }

原逻辑必须等 iframe 的 load 事件触发后,才开始轮询 iframe document 是否准备好。

在当前 iOS Safari 环境中,这个隐藏 iframe 的 load 事件没有稳定触发,导致 Promise 一直不 resolve,于是 html2canvas 日志停在:

text 复制代码
Starting document clone...

这也是为什么业务 DOM 和极简 DOM 都失败。

修复方案

修复思路是:不要完全依赖 iframe 的 load 事件。注册 onload 的同时,立即启动一次相同的检查逻辑。

补丁后的 In 函数:

js 复制代码
In=function(B){

    return new Promise(function(e,A){

        var t=B.contentWindow;

        if(!t)return A("No window assigned for iframe");

        var r=t.document,n=function(){

            t.onload=B.onload=null;

            var A=setInterval(function(){

                r.body&&0<r.body.childNodes.length&&("complete"===r.readyState||"interactive"===r.readyState)&&(clearInterval(A),e(B))

            },50)

        };

        t.onload=B.onload=n,setTimeout(n,0)

    })

}

相比原逻辑,改动点有三个:

  1. onload 回调提取成 n

  2. 保留原来的 t.onload = B.onload = n

  3. 增加 setTimeout(n, 0),避免 iframe load 事件不触发时永久卡住。

同时轮询条件也做了兼容:

js 复制代码
r.body &&

0 < r.body.childNodes.length &&

("complete" === r.readyState || "interactive" === r.readyState)

这样 iframe document 已经进入 interactive 状态时也可以继续。

验证方式

在移动端 vConsole 中验证最小 DOM:

js 复制代码
testHtml2canvas141()

成功后再验证当前业务 DOM:

js 复制代码
testHtml2canvasCurrentDom()

最终结果:

  • 最小 DOM 可以生成 canvas。

  • 当前业务 DOM 可以继续生成图片。

  • 1.4.1 的样式表现优于旧 plugin 版本。

经验总结

这次问题容易被误判成业务 DOM 或 CSS 问题,因为 html2canvas 的报错栈经过压缩后很难直接读,vConsole 里显示的 t.match 也不一定是根因。

更有效的排查路径是:

  1. 先确认实际加载的是哪一个 html2canvas 文件。

  2. 用极简 DOM 做最小复现。

  3. 如果极简 DOM 也失败,就优先排查 html2canvas 初始化、clone、iframe、资源加载这些基础流程。

  4. 观察 html2canvas 日志停在哪一步。

本次的关键判断点是:极简 DOM 也卡在 Starting document clone...,所以问题不在业务 DOM,而在 1.4.1 的隐藏 iframe clone 等待逻辑。

相关推荐
IT_陈寒9 分钟前
SpringBoot自动配置失效?你可能漏了这个小开关
前端·人工智能·后端
kyriewen12 分钟前
我写了1个复盘Skill,和AI协作踩过的坑第二天自动变成护栏
前端·程序员·ai编程
风骏时光牛马12 分钟前
AI提示词异常故障复盘分析
前端
SoaringHeart44 分钟前
Flutter 进阶:NCanvasImageLoader 让 Canvas 也能画网络图
前端·flutter
计算机魔术师1 小时前
英伟达两个月叫停360亿美元生意:芯片巨头怕了反垄断?
前端
创新技术阁1 小时前
FastapiAdmin 前后端启动全流程详解
前端·后端·fastapi
七牛开发者1 小时前
实测推荐 3 个 Skill,轻松上手 Codex 网页设计与交付流程
前端·javascript·后端
七牛开发者1 小时前
拆解 dsh 系列:从源码和版本变化看 DeepSeek Harness 的设计取舍
前端·javascript·后端
谭光志1 小时前
如何从网站提取设计风格:DOM、计算样式与 DESIGN.md
前端·javascript·agent
深念Y2 小时前
登录日志与管理员审计日志存储决策
前端·arm开发·后端·微服务·云原生·架构