Html2canvas: 如何在“溢出:自动”div 中渲染完整的隐藏部分

创建于 2012-02-22  ·  34评论  ·  资料来源: niklasvh/html2canvas

我有一个 div,其中包含必须转换为图像的所有元素。 该 div 设置为“溢出:自动”。 我想知道如何将所有元素(甚至隐藏在滚动中)导出到图像中。 我感谢并欢迎您的所有评论和答案......提前致谢......

最有用的评论

@ruthraprakash ,我遇到了类似的问题。 这适用于我在最新版本上的简单目的:

function fullhtml2canvas(el) {
    return new Promise(resolve => {
        html2canvas(el, {
            width: el.scrollWidth,
            height: el.scrollHeight,
        }).then(canvas => {
            resolve(canvas);
        });
    });
}

所有34条评论

当前没有使用特定选项呈现页面的选项,因此您需要修改页面以使其看起来像您希望呈现的方式。

换句话说,如果您删除高度/宽度限制,运行 html2canvas,然后将高度/宽度设置回原来的值,您应该实现您想要的。

非常感谢....我会试试你说的...

我尝试了很长时间......但它带来了很多问题......我无法实现你所说的。 我发现它在“身体”时运行良好,即使有滚动......我想为具有滚动元素的 div 实现相同的效果......如果你能帮我解决这个问题,那就是对我有很大帮助...我期待着您的评论...

@niklasvh ,我遇到了同样的问题,我唯一的解决方法是在调用html2canvas (并不总是一个选项)之前缩小目标元素的宽度,或者调用html2canvas在同一元素上连续两次。 这是一个演示问题的小提琴:

http://jsfiddle.net/fMeRC/1/ (此特定示例仅适用于 Chrome;您必须调整宽度才能在其他浏览器中查看问题)

这基本上只在元素比窗口或(document.width - 8)宽时才会发生,我不确定哪个具有更重要/更直接的相关性,这可能会在其他浏览器上发生变化)。

可能相关:#199 和#108。

尝试 childElement 或设置“overflow=visible”并设置“overflow=auto|hidden|inherit”之后?

childElement 没有样式,只接收带有溢出的 div 的内容:

<div id="main"><!--// main div -->
<div class="mainContent"><!--// div without style (height: auto, width: auto, margin: 0, padding: 0) -->
...content...
html2canvas([$("#main div.mainContent").get(0)],...)

感谢您的建议,@brcontainer。 我尝试过overflow: visible -> html2canvas( ... ) -> overflow: [old overflow]方法,尽管隐藏/未隐藏/再次隐藏内容的闪烁太明显(可能是因为我的目标元素比较复杂)。 虽然我只是想出了一个稍微优化的变通方法,但似乎在这方面有所不同:

html2canvas( targetElement, {
  onpreloaded: function(){ /* set parent overflow to visible */},
  onparsed: function(){  /* reset parent overflow */ },
  // ... onrendered, etc.
});

这将溢出设置为“可见”,仅在(我认为是)h2c 正确解析目标所需的最短时间,从而几乎完全消除闪存,至少在我的情况下。 也就是说,在重置/重新隐藏溢出之前,我们不再需要等待画布渲染步骤完成。 我不知道这种修改后的方法是否适用于每个人,但我确实认为它比连续两次调用html2canvas( ... )或向 DOM 添加额外内容以包装目标内容更好的解决方法。

无论如何,这仍然是一个真正的错误,我希望看到正确修复。 (特别是因为这两种解决方法在 IE9 和 10 中对我来说似乎都不起作用,至少在 IE11 中没有尝试过。)

_注意:上述解决方法不适用于当前处于 master 中的最新版本。 我还没有测试过,但看起来您需要改用oncloned选项,并且溢出父重置现在将在您的回调中调用.then() 。 (也应该可以在克隆的文档中专门使父级的溢出可见,而根本不用担心重置任何内容。)_

我不明白你为什么用这种方式,最好是这样:

function SnapShotDOM(target,call){
    var data = {};

    //use jquery or getComputedStyle|style.overflow
    data.overflow = /*get overflow property*/;
    data.width = /*get width property*/;
    data.height = /*get height property*/;
    data.maxWidth = /*get maxWidth property*/;
    data.maxHeight = /*get maxHeight  property*/;

    target.style.overflow="visible !important";
    target.style.height="auto !important";
    target.style.maxHeight="auto !important";

    html2canvas(target, {
        "onrendered": function(canvas) {
            target.style.overflow = data.overflow;
            target.style.width = data.width;
            target.style.height = data.height;
            target.style.maxWidth = data.maxWidth;
            target.style.maxHeight = data.maxHeight;
            call(canvas);
        }
    });
}

SnapShotDOM(document.body,function(canvas){
    console.log(canvas);
});

或使用类:

<style>
*.html2canvasreset{
    overflow: visible !important;
    width: auto !important;
    height: auto !important;
    max-height: auto !important;
}
</style>
<script>
function SnapShotDOM(target,call){
    var data = target.className;
    target.className += " html2canvasreset";//set className - Jquery: $(target).addClass("html2canvasreset");
    html2canvas(target, {
        "onrendered": function(canvas) {
            target.className = data;//old className - Jquery: $(target).removeClass("html2canvasreset");
            call(canvas);
        }
    });
}

SnapShotDOM(document.body,function(canvas){
    console.log(canvas);
});
</script>

我没有在onrendered放置任何与溢出相关的内容的原因是因为解析和渲染之间的时间可能很明显,并且尽快重置溢出(即,在解析之后,在渲染之前)更可取以避免内容的可见闪光。 将溢出重置放在onparsed可以实现这一点。

我指的是“预加载”。

尝试这个:

function SnapShotDOM(target,call){
    var data = target.className;
    target.className += " html2canvasreset";//set className - Jquery: $(target).addClass("html2canvasreset");
    html2canvas(target, {
        "onparsed": function() {
            target.className = data;//old className - Jquery: $(target).removeClass("html2canvasreset");
        },
        "onrendered": function(canvas) {
            call(canvas);
        }
    });
}

SnapShotDOM(document.body,function(canvas){
    console.log(canvas);
});

我使用onpreloaded也是出于同样的原因——它是一种优化,它允许我将溢出取消隐藏部分移动到最新的可能时刻,就在解析步骤之前,从而最大限度地减少分析步骤的时间内容在屏幕上完全可见。 您可以在此处此处的代码中了解其工作原理。

@niklasvh ,这个问题是否与此处找到的 TODO( options.useOverflow )有关?

你们用的是什么版本?.. 我可以在我的版本中找到 onparsed 和 onpreloaded 方法..
我使用 html2canvas-0.5.0-alpha1

@ejlocop这个问题是几年前为以前的版本提交的,可能与您的用例无关(#511)。

他们解决了问题? paraa 解决方案我正在寻找带有我的甘特图的东西,我完全需要你......
overflow

@pkpatels为什么不工作? 我运行了您的小提琴,并且在没有切断的情况下呈现了句子......
我也遇到了这个问题,对我有用的解决方案是:#117

@uriklar它适用于水平滚动而不适用于垂直滚动。 查看我的 div。 那里有三个不同的元素。

@uriklar当我向下滚动 div 并单击完全可见时,您建议的解决方案也不起作用。
screen shot 2016-03-16 at 1 41 09 pm

在渲染之前将 #text div 的高度设置为 auto 并在渲染之后重置它怎么样? 那可行。

在最新版本 (0.5.0-beta4) 中,我仍然遇到溢出问题。 我采用了@usmonster的解决方法,并将其调整为最近对 h2c 和 Promises 的更改(如@usmonster的注释中所述):

注意:上述解决方法不适用于当前处于 master 中的最新版本。 我还没有测试过,但看起来您需要改用 oncloned 选项,现在将在您对 .then() 的回调中调用溢出父重置。 (也应该可以在克隆的文档中专门使父级的溢出可见,而根本不用担心重置任何内容。)

因此,无需更改网页的实际 DOM,您就可以使用onclone回调来更改 h2c 用于渲染的克隆文档。 实际上很简单,这是我的 h2c 调用:

var renderingPromise = html2canvas($(item), {
    width: item.clientWidth,
    height: item.clientHeight,
    onclone: function(clone) {
            $(clone).find('.grid-stack-item-content')
                .css('overflow-x', 'auto')
                .css('overflow-y', 'auto');
        return true;
    }
}).then(
    function(c) {/* success */},
    function() {/* fail */}
);

唯一对我有用的是将画布放在 iframe 中,在其中调用 html2canvas,在画布上调用 toDataURL(),然后使用回调将该图像传递回顶部窗口。 我想你也可以传回一个画布对象。

return renderDocument(node.ownerDocument, options, node.ownerDocument.defaultView.innerWidth, node.ownerDocument.defaultView.innerHeight, index).then(function(canvas) { if (typeof(options.onrendered) === "function") { log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"); options.onrendered(canvas); } return canvas; });
改成
var width = options.width != null ? options.width : node.ownerDocument.defaultView.innerWidth; var height = options.height != null ? options.height+node.ownerDocument.defaultView.innerHeight : node.ownerDocument.defaultView.innerHeight; return renderDocument(node.ownerDocument, options, width, height, index).then(function (canvas) { if (typeof(options.onrendered) === "function") { log("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"); options.onrendered(canvas); } return canvas; });

这样可以解决屏幕溢出(宽高)的问题

xzw123 有一个糟糕的解决方案:手动设置ownerDocument.defaultView.innerHeight会导致它与实际的窗口大小事件解除绑定。 我认为最好在 iframe 中执行此操作。 我很想尝试乔丹的解决方案。

Jordan,你是如何在 iframe 中使用画布的? 我现在正在尝试。 我认为这应该是 html2canvas 中的最终解决方案...... iframe 通信应该在 API 外部不可见。

啊,是的,在 iframe 中用window.postMessage(myData, ... )做就可以了。 您可以回发渲染像素的整个数据 url。 我只是把我的渲染代码放在 iframe 的 HTML 中,传入渲染 HTML 源所需的数据,让它渲染到画布,然后让它吐出 toDataUrl 数据。

+1

你好。 在搜索解决方案并观察代码运行方式后,我编写了自己的棘手解决方案。

https://gist.github.com/simonmysun/c6da13ce2827a374e71ccf07d9f08e2d

它对我有用,我希望它能帮助需要的人。

但是,我仍然希望将来可以在这个库中支持它。

我仍然不明白,但我的问题是图像被切断了。 使用 chrome 版本 54.0.2840.99 m 时
(一半图片被截屏,另一半黑屏)

// the timeline show up 100%, but cut off, cause its static and not dynamic.
// (its cut off from the screen,but the size, and picture show as normal, 100% show)
// after moving to the canvas, everthing that not in the screen will get blank in chrome  
// it depends to the user screen, if i zoom out my chrome, i get 100% image.

但是当使用 Mozilla 50.0.2 时,它在没有缩小的情况下工作正常。 (100% 图像),

我不知道为什么。

代码 :

var zenleft = $("#leftPanel").width();  //calculate left side
var zenright = $(".dataPanel").width();  //calculate right side
var after = zenright + zenleft + 250;  // add all

//add the css, even after add overflow still not working
$("#timelineTarget").css({"background-color":"white","width":after});   

 html2canvas(canvTimeline, {
    onrendered: function (canvas) {
            $("#previewImage").html(canvas);
            getCanvas = canvas;
   }
});

image

最后我通过添加来解决这个问题

$("body").css({"width": "+="+after}); //after is a total of the width of the element i want to view

所以

var zenleft = $("#leftPanel").width();  //calculate left side
var zenright = $(".dataPanel").width();  //calculate right side
var after = zenright + zenleft + 250;  // add all
$("body").css({"width": "+="+after});  //add the body

//add the css
$("#timelineTarget").css({"background-color":"white","width":after});   

 html2canvas(canvTimeline, {
    onrendered: function (canvas) {
            $("#previewImage").html(canvas);
            $("#timelineTarget").css({"background-color":"white","width":old});   //turn it back
            $("body").css({"width": "-="+after});   //turn it back
            getCanvas = canvas;
   }
});

希望它能解决你自己的问题。

onclone可能是正确的方法。 你可以改变css来得到你想要的......

大家好,我有可滚动的 div。 当我将 div 输入作为画布参数发送时,它只是渲染视口中可用的内容。 我经历了所有解决方案。 我不明白。 谁能告诉如何将 div 中的整个内容作为屏幕截图。

@ruthraprakash ,我遇到了类似的问题。 这适用于我在最新版本上的简单目的:

function fullhtml2canvas(el) {
    return new Promise(resolve => {
        html2canvas(el, {
            width: el.scrollWidth,
            height: el.scrollHeight,
        }).then(canvas => {
            resolve(canvas);
        });
    });
}

我在截取时间线图表的屏幕截图时遇到问题。 我没有得到 x 轴值。 它只是创建时间线图的图像。
` demoFromHTML(e) {
e.preventDefault();

  let input = window.document.getElementById('divToPDF');


  html2canvas(input)
  .then((canvas) => {

    const imgData = canvas.toDataURL('image/jpeg');

    const pdf = new pdfConverter("l", "pt");
    pdf.addImage(imgData, 'JPEG', 15, 110, 800, 250);
    pdf.save('test.pdf');
  });


}

`

我尝试了很长时间......但它带来了很多问题......我无法实现你所说的。 我发现它在“身体”时运行良好,即使有滚动......我想为具有滚动元素的 div 实现相同的效果......如果你能帮我解决这个问题,那就是对我有很大帮助...我期待着您的评论...

请你告诉我你是如何让身体工作的

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

deepender87 picture deepender87  ·  4评论

bishwapoudel picture bishwapoudel  ·  4评论

anthonymejia picture anthonymejia  ·  4评论

Josh10101010 picture Josh10101010  ·  3评论

wbarrantes picture wbarrantes  ·  3评论