【问题标题】:Html2canvas renders page with wrong layout in IE11 whed devtools not opened未打开 devtools 时,Html2canvas 在 IE11 中呈现布局错误的页面
【发布时间】:2018-06-22 20:43:21
【问题描述】:

我正在尝试修复与通过 IE11 中的 html2canvas 将网页渲染到画布相关的错误。问题有点令人困惑:网站使用 bootstrap 2.3 网格实现负责任的布局。

  1. 当开发者工具未打开时,其呈现方式类似于桌面/智能手机屏幕

  2. 但如果我按 F12(开发者工具打开,没有执行任何其他操作)并单击以呈现页面它按预期呈现,适用于宽屏

删除了旧应用程序的过时链接。不是它不存在于指定的地址。

这个问题只在IE11上重现,打开devtool后就消失了,所以我不知道怎么调试。

【问题讨论】:

  • 开发工具未打开时是否默认为 Quirks 模式?在 Dev 工具中将 Document Mode 设置为 Quirks,看看它是否和 Dev 工具打开前一样。
  • @ericjbasti,在 IE11 中,文档模型中没有这样的选项。只有“边”、“10”、“9”、“8”、“7”和“5”。
  • 我也没有在头部看到<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> 的元标记。不过你的 DOCTYPE 看起来不错。
  • @ericjbasti 此站点不适用于 IE8 及更低版本。在 10 和 9 中,所有工作方式都相同 - 关闭 devtools 时的移动布局和打开时的宽屏。
  • 尝试添加meta标签(我之前测试过) - 没有效果,真是令人困惑的bug。

标签: twitter-bootstrap html2canvas


【解决方案1】:

我其实不知道IE11到底是什么鬼,但我找到了一个快速的猴子补丁方法来解决它:

return new Promise(function(resolve) {
        var documentClone = container.contentWindow.document;

        /* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
         if window url is about:blank, we can assign the url to current by writing onto the document
         */
        container.contentWindow.onload = container.onload = function() {
            var interval = setInterval(function() {
                if (documentClone.body.childNodes.length > 0) {
                    initNode(documentClone.documentElement);
                    clearInterval(interval);
                    if (options.type === "view") {
                        container.contentWindow.scrollTo(x, y);
                        if ((/(iPad|iPhone|iPod)/g).test(navigator.userAgent) && (container.contentWindow.scrollY !== y || container.contentWindow.scrollX !== x)) {
                            documentClone.documentElement.style.top = (-y) + "px";
                            documentClone.documentElement.style.left = (-x) + "px";
                            documentClone.documentElement.style.position = 'absolute';
                        }
                    }
                    resolve(container);
                }
            }, 50);
        };

        documentClone.open();
        documentClone.write("<!DOCTYPE html><html></html>");
        // Chrome scrolls the parent document for some reason after the write to the cloned window???
        restoreOwnerScroll(ownerDocument, x, y);
        documentClone.replaceChild(documentClone.adoptNode(documentElement), documentClone.documentElement);

        /*
           #HERE
           1) It seems IE 11 does not get right computed styles when clones a node (See function cloneNode) above.
           2) In documentClone.replaceChild(...) IE 11 does not apply @media instructions.
              That's can be checked
                  by alert('ndocumentClone ' + $('.row-fluid [class*="span"]', documentClone).css('float'));
                  or alert('documentElement ' + $('.row-fluid [class*="span"]', documentElement).css('float'));
              These both statments shows 'left' for wide screen in Chrome and shows none in IE11 (without dev panel).
            To fix that we need to re-apply styles somehow. Change the container width works but probably a better
            way exists. Lets have this in mind.
         */
        container.width = width + 1;
        /* * */

        documentClone.close();
    });

【讨论】:

  • 今天遇到了同样的问题。在我来到这个线程之前花了很多时间调试。整个代码可以保持原样。重要的是 container.width = width + 1;太感谢了。赞成。
  • 如果您使用 bower,这不是一个好方法。在我看来,你需要在不操纵库的情况下解决这个问题。我正在寻找同样的方法来做到这一点......
  • 版本 1.0.0-alpha.12 cloneIframeContainer.width = (bounds.width + 1).toString(); 为我工作。
【解决方案2】:

以防万一有人像我一样遇到这种情况: html2canvas 提供了一个 onclone-method,在该方法中您可以在生成屏幕截图之前触摸 DOM。这也会触发 IE11 中样式的重新计算。

html2canvas(
        document.body,
        {
            allowTaint: true,
            logging: false,
            onclone: function(document) {
                return $q(
                    function(resolve) {
                        $timeout(function() {
                            document.body.innerHTML = document.body.innerHTML; //<-- Hackerman was here
                            resolve();
                        }, 0);
                });
            }
        }
);

这对我有用,好处是我不必修改从 npm 获得的实现。 - 虽然如果有人有更好的解决方案我会喜欢它,因为这看起来很hacky

【讨论】:

    猜你喜欢
    • 2014-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 2012-12-19
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    相关资源
    最近更新 更多