Html2canvas: So rendern Sie in 'overflow:auto' div . voll versteckte Teile

Erstellt am 22. Feb. 2012  ·  34Kommentare  ·  Quelle: niklasvh/html2canvas

Ich habe ein div, das alle Elemente enthält, die in ein Bild umgewandelt werden müssen. Und dieses div ist auf ' overflow:auto ' gesetzt. Ich möchte wissen, wie ich alle Elemente (auch beim Scrollen versteckt) in ein Bild exportieren kann. Ich schätze und begrüße alle Ihre Kommentare und Antworten...... Vielen Dank im Voraus...

Hilfreichster Kommentar

@ruthraprakash , ich hatte ein ähnliches Problem. Dies funktioniert für meine einfachen Zwecke in der neuesten Version:

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

Alle 34 Kommentare

Derzeit gibt es keine Option zum Rendern der Seite mit bestimmten Optionen, daher müssen Sie die Seite so ändern, dass sie so aussieht, wie sie gerendert werden soll.

Mit anderen Worten, wenn Sie die Höhen-/Breitenbegrenzung entfernen, html2canvas ausführen und dann die Höhe/Breite auf den ursprünglichen Wert zurücksetzen, sollten Sie das erreichen, wonach Sie suchen.

Vielen Dank ... Ich werde versuchen, was Sie gesagt haben ...

Ich habe es lange versucht... Aber es macht eine Menge Probleme... Ich konnte nicht erreichen, was du gesagt hast. Ich habe herausgefunden, dass es gut funktioniert, wenn es 'body' ist, auch wenn es Scrollen gibt ... Ich möchte dasselbe für ein div erreichen, das Elemente mit Scrollen hat ... Wenn Sie mir bei diesem Problem helfen könnten, wäre es eine große Hilfe für mich... Ich freue mich auf Ihre Kommentare...

@niklasvh , ich habe das gleiche Problem und die einzige Zielelements vor dem Aufruf auf html2canvas zu verkleinern (nicht immer eine Option) oder html2canvas aufzurufen

http://jsfiddle.net/fMeRC/1/ (dieses spezielle Beispiel funktioniert nur für Chrome; Sie müssen mit der Breite herumspielen, um das Problem in anderen Browsern zu sehen)

Dies geschieht im Grunde nur, wenn das Element breiter als das Fenster ist oder (document.width - 8) , ich bin mir nicht sicher, welches die wichtigere / direktere Relevanz hat, und dies kann sich bei anderen Browsern ändern).

Wahrscheinlich verwandt: #199 und #108.

ChildElement probiert oder "overflow=visible" gesetzt und nach set "overflow=auto|hidden|inherit" ?

childElement ohne Stil, nur um den Inhalt des div mit Überlauf zu erhalten:

<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)],...)

Danke für die Vorschläge, @brcontainer. Ich hatte den Ansatz overflow: visible -> html2canvas( ... ) -> overflow: [old overflow] ausprobiert, obwohl das Aufblitzen des versteckten/unversteckten/wiederversteckten Inhalts zu auffällig war (möglicherweise weil mein Zielelement ist relativ komplex). Allerdings habe ich mir gerade eine leicht optimierte Variante des Workarounds ausgedacht, die in dieser Hinsicht einen Unterschied zu machen scheint:

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

Dadurch wird der Überlauf nur für die kürzeste Zeit, die h2c benötigt, um das Ziel richtig zu analysieren, auf "sichtbar" gesetzt (was meiner Meinung nach ist), wodurch der Blitz, zumindest in meinem Fall, fast vollständig eliminiert wird. Das heißt, wir müssen nicht mehr warten, bis der Canvas-Rendering-Schritt abgeschlossen ist, bevor wir den Überlauf zurücksetzen/wieder ausblenden. Ich habe keine Ahnung, ob dieser modifizierte Ansatz für alle funktioniert, aber ich denke, es ist eine schönere Problemumgehung, als html2canvas( ... ) zweimal hintereinander aufzurufen oder zusätzliches Zeug zum DOM hinzuzufügen, um den Zielinhalt zu umschließen.

Auf jeden Fall ist dies immer noch ein echter Fehler, den ich gerne richtig behoben sehen würde. (Zumal keine Problemumgehung für mich zumindest in IE9 und 10 korrekt zu funktionieren scheint - habe es in IE11 nicht versucht.)

_Hinweis: Die oben genannte Problemumgehung würde mit der neuesten Version, die sich derzeit im Master befindet, nicht funktionieren. Ich habe es nicht getestet, aber es sieht so aus, als müssten Sie stattdessen die Option oncloned verwenden, und das Zurücksetzen der Überlauf-Eltern wird jetzt in Ihrem Rückruf zu .then() aufgerufen. (Es sollte auch möglich sein, den Überlauf des Elternteils ausschließlich innerhalb des geklonten Dokuments sichtbar zu machen und sich keine Gedanken über das Zurücksetzen zu machen.)_

Ich verstehe nicht, warum Sie es so verwenden, es wäre besser so:

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);
});

oder Klasse verwenden:

<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>

Der Grund, warum ich nichts im Zusammenhang mit Überlauf in onrendered schreibe, ist, dass die Zeit zwischen Parsing und Rendern spürbar sein kann und es vorzuziehen ist, den Überlauf so schnell wie möglich zurückzusetzen (dh direkt nach dem Parsing, vor dem Rendern). um ein sichtbares Aufblitzen von Inhalten zu vermeiden. Setzen Sie stattdessen den Überlauf-Reset in onparsed um dies zu erreichen.

Ich meinte "onpreloaded".

Versuche dies:

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);
});

Meine Verwendung von onpreloaded hat den gleichen Grund - es ist eine Optimierung, die es mir ermöglicht, den Teil zum Einblenden des Überlaufs auf den spätestmöglichen Zeitpunkt kurz vor dem Parsing-Schritt zu verschieben, wodurch die Zeit minimiert wird, für die es erforderlich ist der Inhalt ist vollständig auf dem Bildschirm sichtbar. Sie können sehen, wie dies im Code hier und hier funktioniert.

@niklasvh , hängt dieses Problem überhaupt mit der TODO hier zusammen ( options.useOverflow )?

Welche Version habt ihr verwendet? .. Ich kann die Methode onparsed und onpreloaded in meiner Version finden..
ich benutze html2canvas-0.5.0-alpha1

@ejlocop Dieses Problem wurde vor Jahren für eine frühere Version eingereicht und ist möglicherweise für Ihren Anwendungsfall (#511) nicht relevant.

Sie haben das Problem gelöst? paraa-Lösung Ich suche etwas mit meinem Gantt-Diagramm, ich brauche dich komplett...
overflow

es funktioniert nicht.

http://jsfiddle.net/fMeRC/368/

@pkpatels Warum nicht arbeiten? Ich habe deine Geige gespielt und die Sätze wurden wiedergegeben, ohne abzuschneiden...
Ich hatte auch dieses Problem und die Lösung, die für mich funktioniert hat, ist die vorgeschlagene in: #117

@uriklar Es funktioniert für horizontales

@uriklar Die von Ihnen klicke .
screen shot 2016-03-16 at 1 41 09 pm

Wie wäre es, wenn Sie die Höhe von #text div vor dem Rendern auf Auto setzen und sie danach zurücksetzen? Das wird funktionieren.

Ich hatte immer noch Probleme mit dem Überlauf in der neuesten Version (0.5.0-beta4). Ich habe den Workaround von @usmonster genommen und an die jüngsten Änderungen an h2c und Promises angepasst (wie in @usmonsters Anmerkung beschrieben):

Hinweis: Die oben genannte Problemumgehung würde mit der neuesten Version, die sich derzeit im Master befindet, nicht funktionieren. Ich habe es nicht getestet, aber es sieht so aus, als müssten Sie stattdessen die oncloned-Option verwenden, und das Zurücksetzen der Überlauf-Eltern wird jetzt in Ihrem Rückruf zu .then() aufgerufen. (Es sollte auch möglich sein, den Überlauf des Elternteils ausschließlich innerhalb des geklonten Dokuments sichtbar zu machen und sich keine Gedanken über das Zurücksetzen zu machen.)

Ohne das tatsächliche DOM Ihrer Webseite zu ändern, können Sie das geklonte Dokument, das für das Rendern von h2c verwendet wird, mit dem onclone Callback ändern. Es ist eigentlich ziemlich einfach, hier ist mein h2c-Aufruf:

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 */}
);

Das einzige, was für mich funktioniert hat, war, die Leinwand in einen iframe zu legen, html2canvas darin aufzurufen, toDataURL() auf der Leinwand aufzurufen und dann dieses Bild mit einem Rückruf an das obere Fenster zurückzugeben. Ich nehme an, Sie könnten auch ein Canvas-Objekt zurückgeben.

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; });
ändern
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; });

Dies kann die Frage nach dem Überlauf des Bildschirms (sowohl Breite als auch Höhe) lösen.

xzw123 hat eine schlechte Lösung: Wenn Sie ownerDocument.defaultView.innerHeight manuell festlegen, wird die Bindung von den tatsächlichen Fenstergrößenereignissen getrennt. Ich denke, es wäre am besten, dies in einem iframe zu tun. Ich würde gerne Jordans Lösung ausprobieren.

Jordan, wie sind Sie dazu gekommen, Canvas in einem Iframe zu verwenden? Ich versuche es jetzt. Ich denke, dies sollte die endgültige Lösung in html2canvas sein ... die iframe-Kommunikation sollte außerhalb der API unsichtbar gemacht werden.

Ah ja, es in einem iframe mit window.postMessage(myData, ... ) tun, macht den Trick. Sie können die gesamte Daten-URL der gerenderten Pixel zurücksenden. Ich füge einfach meinen Rendering-Code in den HTML-Code des Iframes ein, übergebe die Daten, die zum Rendern der HTML-Quelle erforderlich sind, lasse ihn in die Leinwand rendern und lasse ihn dann die toDataUrl-Daten wieder ausspucken.

+1

Hi. Nachdem ich nach Lösungen gesucht und beobachtet habe, wie der Code abläuft, schreibe ich meine eigene knifflige Lösung.

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

Es funktioniert für mich und ich hoffe, es wird jemandem helfen, der es braucht.

Ich hoffe jedoch immer noch, dass es in Zukunft in dieser Bibliothek unterstützt werden kann.

Ich verstehe es immer noch nicht, aber für mein Problem ist das Bild abgeschnitten. bei Verwendung von Chrom Version 54.0.2840.99 m
(ein halbes Bild wurde gescreent, aber die andere Hälfte hat einen schwarzen Bildschirm)

// 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.

Aber wenn Sie Mozilla 50.0.2 verwenden, funktioniert es ohne Verkleinern einwandfrei. (100% Bild),

ich weiß nicht warum.

Code:

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

Schließlich löse ich dieses Problem, indem ich hinzufüge

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

so

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;
   }
});

hoffe es löst dein eigenes problem.

onclone ist vielleicht die richtige Methode. Sie können CSS ändern, um zu bekommen, was Sie wollen....

Hallo zusammen, ich habe div, das scrollbar ist. Wenn ich die div-Eingabe als Canvas-Parameter sende, wird nur das gerendert, was im Viewport verfügbar ist. Ich bin alle Lösungen durchgegangen. Ich habe es nicht verstanden. Kann mir jemand sagen, wie man den gesamten Inhalt in div als Screenshot aufnimmt?

@ruthraprakash , ich hatte ein ähnliches Problem. Dies funktioniert für meine einfachen Zwecke in der neuesten Version:

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

Ich habe ein Problem mit dem Erstellen eines Screenshots des Zeitachsendiagramms. Ich erhalte den Wert der x-Achse nicht. es erstellt nur das Bild des Zeitachsendiagramms.
` 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');
  });


}

`

Ich habe es lange versucht... Aber es macht eine Menge Probleme... Ich konnte nicht erreichen, was du gesagt hast. Ich habe herausgefunden, dass es gut funktioniert, wenn es 'body' ist, auch wenn es Scrollen gibt ... Ich möchte dasselbe für ein div erreichen, das Elemente mit Scrollen hat ... Wenn Sie mir bei diesem Problem helfen könnten, wäre es eine große Hilfe für mich... Ich freue mich auf Ihre Kommentare...

Kannst du mir bitte zeigen, wie du deinen Körper zum Arbeiten gebracht hast?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen