it-swarm.com.de

Rendern Sie HTML in ein Bild

Gibt es eine Möglichkeit, HTML-Bilder wie PNG zu rendern? Ich weiß, dass dies mit Canvas möglich ist, aber ich würde gerne Standard-HTML-Elemente wie div darstellen.

109
Martin Delille

Alle Antworten verwenden Bibliotheken von Drittanbietern. Das Rendern von HTML in ein Bild kann in reinem Javascript relativ einfach sein. Dort ist war sogar ein Artikel darüber im Canvas-Bereich von MDN.

Der Trick ist folgender:

  • erstellen Sie eine SVG mit einem ForeignObject-Knoten, der Ihre XHTML enthält
  • setzen Sie die SRC eines Bildes auf die Daten-URL dieser SVG
  • drawImage auf der Leinwand
  • legen Sie die Canvas-Daten auf target image.src fest

const {body} = document

const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = canvas.height = 100

const tempImg = document.createElement('img')
tempImg.addEventListener('load', onTempImageLoad)
tempImg.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml"><style>em{color:red;}</style><em>I</em> lick <span>cheese</span></div></foreignObject></svg>')

const targetImg = document.createElement('img')
body.appendChild(targetImg)

function onTempImageLoad(e){
  ctx.drawImage(e.target, 0, 0)
  targetImg.src = canvas.toDataURL()
}

Einige Dinge zu beachten

  • Der HTML-Code im SVG muss XHTML sein
  • Aus Sicherheitsgründen fungiert die SVG als Daten-URL eines Bildes als isolierter CSS-Bereich für HTML, da keine externen Quellen geladen werden können. So muss beispielsweise eine Google-Schriftart mit einem Tool wie this Inline eingebettet werden.
  • Selbst wenn der HTML-Code in der SVG-Datei die Größe des Bildes überschreitet, wird er korrekt auf die Leinwand gezeichnet. Die tatsächliche Höhe kann jedoch nicht von diesem Bild aus gemessen werden. Eine Lösung mit fester Höhe funktioniert einwandfrei, aber die dynamische Höhe erfordert etwas mehr Arbeit. Am besten rendern Sie die SVG-Daten in einen Iframe (für isolierten CSS-Bereich) und verwenden die resultierende Größe für die Leinwand.
19
Sjeiti

Ja. HTML2Canvas existiert, um HTML auf <canvas> zu rendern (das Sie dann als Bild verwenden können).

HINWEIS: Es ist ein bekanntes Problem, dass dies mit SVG nicht funktioniert

91
AKX

Darf ich die dom-to-image library empfehlen, die ausschließlich für dieses Problem geschrieben wurde (ich bin der Betreuer).
So verwenden Sie es (einige hier ):

var node = document.getElementById('my-node');

domtoimage.toPng(node)
    .then (function (dataUrl) {
        var img = new Image();
        img.src = dataUrl;
        document.appendChild(img);
    })
    .catch(function (error) {
        console.error('oops, something went wrong!', error);
    });
69
tsayen

Es gibt viele Möglichkeiten und sie haben alle ihre Vor- und Nachteile. 

Option 1: Verwenden Sie eine der vielen verfügbaren Bibliotheken

Pros

  • Die Konvertierung ist meistens ziemlich schnell

Cons

  • Schlechtes Rendering
  • Führt kein Javascript aus
  • Keine Unterstützung für aktuelle Webfunktionen (FlexBox, Advanced Selectors, Webfonts, Box Sizing, Medienabfragen, ...)
  • Manchmal nicht so einfach zu installieren
  • Kompliziert im Maßstab

Option 2: Verwenden Sie PhantomJs und möglicherweise eine Wrapper-Bibliothek

Pros

  • Führen Sie Javascript aus
  • Ziemlich schnell

Cons

  • Schlechtes Rendering
  • Keine Unterstützung für aktuelle Webfunktionen (FlexBox, Advanced Selectors, Webfonts, Box Sizing, Medienabfragen, ...)
  • Kompliziert im Maßstab
  • Nicht so einfach, dass es funktioniert, wenn Bilder geladen werden sollen ...

Option 3: Verwenden Sie Chrome Headless und möglicherweise eine Wrapper-Bibliothek

Pros

  • Führen Sie Javascript aus
  • Nahezu perfektes Rendering

Cons

  • Es ist nicht so einfach, genau das gewünschte Ergebnis zu haben:
    • ladezeit der Seite
    • abmessungen des Ansichtsfensters
  • Kompliziert im Maßstab
  • Ganz langsam und noch langsamer, wenn die HTML-Datei externe Links enthält

Option 4: Verwenden Sie eine API

Pros

  • Führen Sie Javascript aus
  • Nahezu perfektes Rendering
  • Schnell, wenn die Caching-Optionen korrekt verwendet werden
  • Die Skalierung wird von den APIs übernommen
  • Präzises Timing, Viewport, ...
  • Meistens bieten sie einen kostenlosen Plan an

Cons

  • Nicht frei, wenn Sie sie häufig verwenden möchten

Haftungsausschluss: Ich bin der Gründer von ApiFlash. Ich tat mein Bestes, um eine ehrliche und nützliche Antwort zu geben.

36

Sie könnten PhantomJS verwenden, ein Headless-Webkit (die Rendering-Engine in Safari und (bis vor kurzem) Chrom) -Treiber. Sie können lernen, wie Sie eine Bildschirmaufnahme von Seiten hier durchführen. Hoffentlich hilft das!

13
TheContrarian

Sie können ein HTML-Tool für PDF wie wkhtmltopdf verwenden. Und dann können Sie ein PDF für ein Bildwerkzeug wie Imagemagick verwenden. Zugegeben, dies ist serverseitig und ein sehr komplizierter Prozess ...

11
PinnyM

Die einzige Bibliothek, die ich für Chrome, Firefox und MS Edge verwenden konnte, war rasterizeHTML . Es liefert bessere Qualität als HTML2Canvas und wird im Gegensatz zu HTML2Canvas weiterhin unterstützt.

Element holen und als PNG herunterladen

var node= document.getElementById("elementId");
var canvas = document.createElement("canvas");
canvas.height = node.offsetHeight;
canvas.width = node.offsetWidth;
var name = "test.png"

rasterizeHTML.drawHTML(node.outerHTML, canvas)
     .then(function (renderResult) {
            if (navigator.msSaveBlob) {
                window.navigator.msSaveBlob(canvas.msToBlob(), name);
            } else {
                const a = document.createElement("a");
                document.body.appendChild(a);
                a.style = "display: none";
                a.href = canvas.toDataURL();
                a.download = name;
                a.click();
                document.body.removeChild(a);
            }
     });
7
vabanagas

Ich erwarte nicht, dass dies die beste Antwort ist, aber es schien interessant genug zu sein, um etwas zu posten.

Schreiben Sie eine App, die Ihren bevorzugten Browser mit dem gewünschten HTML-Dokument öffnet, die Größe des Fensters richtig ändert und einen Screenshot erstellt. Entfernen Sie dann die Ränder des Bildes.

5
John Fisher

Mit JavaScript alleine können Sie dies nicht 100% ig tun.

Es gibt ein Qt Webkit tool out und eine Python-Version . Wenn Sie es selbst machen wollen, habe ich mit Cocoa Erfolg gehabt:

[self startTraverse:pagesArray performBlock:^(int collectionIndex, int pageIndex) {

    NSString *locale = [self selectedLocale];

    NSRect offscreenRect = NSMakeRect(0.0, 0.0, webView.frame.size.width, webView.frame.size.height);
    NSBitmapImageRep* offscreenRep = nil;      

    offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
                                             pixelsWide:offscreenRect.size.width
                                             pixelsHigh:offscreenRect.size.height
                                             bitsPerSample:8
                                             samplesPerPixel:4
                                             hasAlpha:YES
                                             isPlanar:NO
                                             colorSpaceName:NSCalibratedRGBColorSpace
                                             bitmapFormat:0
                                             bytesPerRow:(4 * offscreenRect.size.width)
                                             bitsPerPixel:32];

    [NSGraphicsContext saveGraphicsState];

    NSGraphicsContext *bitmapContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep];
    [NSGraphicsContext setCurrentContext:bitmapContext];
    [webView displayRectIgnoringOpacity:offscreenRect inContext:bitmapContext];
    [NSGraphicsContext restoreGraphicsState];

    // Create a small + large thumbs
    NSImage *smallThumbImage = [[NSImage alloc] initWithSize:thumbSizeSmall];  
    NSImage *largeThumbImage = [[NSImage alloc] initWithSize:thumbSizeLarge];

    [smallThumbImage lockFocus];
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];  
    [offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];  
    NSBitmapImageRep *smallThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeSmall.width, thumbSizeSmall.height)];  
    [smallThumbImage unlockFocus];  

    [largeThumbImage lockFocus];  
    [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];  
    [offscreenRep drawInRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];  
    NSBitmapImageRep *largeThumbOutput = [[NSBitmapImageRep alloc] initWithFocusedViewRect:CGRectMake(0, 0, thumbSizeLarge.width, thumbSizeLarge.height)];  
    [largeThumbImage unlockFocus];  

    // Write out small
    NSString *writePathSmall = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_small.png", locale, collectionIndex, pageIndex]];
    NSData *dataSmall = [smallThumbOutput representationUsingType:NSPNGFileType properties: nil];
    [dataSmall writeToFile:writePathSmall atomically: NO];

    // Write out lage
    NSString *writePathLarge = [issueProvider.imageDestinationPath stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@-collection-%03d-page-%03d_large.png", locale, collectionIndex, pageIndex]];
    NSData *dataLarge = [largeThumbOutput representationUsingType:NSPNGFileType properties: nil];
    [dataLarge writeToFile:writePathLarge atomically: NO];
}];

Hoffe das hilft!

2
Matt Melton

Installieren Sie Phantomjs

$ npm install phantomjs

Erstellen Sie eine Datei github.js mit folgendem Code

var page = require('webpage').create();
//viewportSize being the actual size of the headless browser
page.viewportSize = { width: 1024, height: 768 };
page.open('http://github.com/', function() {
    page.render('github.png');
    phantom.exit();
});

Übergeben Sie die Datei als Argument an phantomjs

$ phantomjs github.js
1
Saurabh Saxena

Verwenden Sie html2canvas, schließen Sie einfach das Plugin und die Aufrufmethode ein, um HTML in Canvas zu konvertieren, und laden Sie es als PNG-Bild herunter

        html2canvas(document.getElementById("image-wrap")).then(function(canvas) {
            var link = document.createElement("a");
            document.body.appendChild(link);
            link.download = "manpower_efficiency.jpg";
            link.href = canvas.toDataURL();
            link.target = '_blank';
            link.click();
        });

Source: http://www.freakyjolly.com/convert-html-document-into-image-jpg-png-from-canvas/

1
Code Spy

Sie können es sicherlich. Die JavaScript-API von GrabzIt ermöglicht das Erfassen eines Div von einer Webseite wie dieser:

<script type="text/javascript" src="grabzit.min.js"></script>
<script type="text/javascript">
GrabzIt("Your Application Key").ConvertURL("http://www.example.com/my-page.html",
{"target": "#features", "bheight": -1, "height": -1, "width": -1}).Create();
</script>

Dabei ist #features die ID des zu erfassenden div. Wenn Sie HTML in ein Bild konvertieren möchten. Sie können diese Technik verwenden:

GrabzIt("Your Application Key").ConvertHTML(
"<html><body><h1>Hello World!</h1></body></html>").Create();

Disclaimer Ich habe diese API erstellt!

1
GrabzIt

Verwenden Sie diesen Code, wird es sicherlich funktionieren:

<script type="text/javascript">
 $(document).ready(function () {
	 setTimeout(function(){
		 downloadImage();
	 },1000)
 });
 
 function downloadImage(){
	 html2canvas(document.querySelector("#dvContainer")).then(canvas => {
		a = document.createElement('a'); 
		document.body.appendChild(a); 
		a.download = "test.png"; 
		a.href =  canvas.toDataURL();
		a.click();
	});	 
 }
</script>

Vergessen Sie nicht, die Datei Html2CanvasJS in Ihr Programm aufzunehmen . https://html2canvas.hertzen.com/dist/html2canvas.js

0
Mohit Kulkarni

HtmlToImage.jar ist die einfachste Möglichkeit, eine HTML in ein Bild zu konvertieren

HTML in Bild konvertieren mit Java

0

Zeichnen von DOM-Objekten in eine Leinwand zeigt einen schnellen Weg, dies zu erreichen.

Aus Sicht der Leistung sollte diese Methode leicht sein. Weil der svg-Renderer und der dom-Renderer anscheinend Puffer nach Bedarf hin und her übergeben können. Was Sinn macht, denn es ist alles Kerncode.

Ich habe keine Benchmarks davon, aber MDN-Dokumente sind nicht nur für Gecko gut gepflegt. Ich vermute, Sie können zumindest wissen, dass schlechte Leistung ein Thema ist, das an einem bestimmten Punkt behandelt werden wird.

0
Tamir Daniely

Ich weiß, dass dies eine ziemlich alte Frage ist, die bereits viele Antworten hat, und dennoch habe ich stundenlang versucht, das zu tun, was ich wollte:

  • erstellen Sie in einer HTML-Datei ein (PNG-) Bild mit transparent background über die Befehlszeile

Mit Chrome Headless (Version 74.0.3729.157 ab dieser Antwort) ist es tatsächlich einfach:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless --screenshot --window-size=256,256 --default-background-color=0 button.html

Erklärung des Befehls:

  • sie führen Chrome über die Befehlszeile aus (hier für den Mac dargestellt, jedoch unter Windows oder Linux als ähnlich vorausgesetzt).
  • --headless führt Chrome aus, ohne es zu öffnen, und wird nach Abschluss des Befehls beendet
  • --screenshot erstellt einen Screenshot (beachten Sie, dass in dem Ordner, in dem der Befehl ausgeführt wird, eine Datei mit dem Namen screenshot.png erstellt wird)
  • --window-size darf nur einen Teil des Bildschirms erfassen (Format ist --window-size=width,height)
  • --default-background-color=0 ist der Zaubertrick, der Chrome anweist, einen transparenten Hintergrund zu verwenden, nicht die standardmäßige weiße Farbe
  • schließlich geben Sie die HTML-Datei (als URL entweder lokal oder remote ...)
0
yan