web-dev-qa-db-fra.com

Rendre le HTML en image

Existe-t-il un moyen de rendre le code HTML en image au format PNG? Je sais que c’est possible avec canvas mais je voudrais rendre l’élément HTML standard comme div par exemple.

109
Martin Delille

Toutes les réponses ici utilisent des bibliothèques tierces tandis que le rendu HTML en image peut être relativement simple en Javascript pur. Là est était même un article à ce sujet sur la section de toile sur MDN.

L'astuce est la suivante:

  • créer un fichier SVG avec un noeud foreignObject contenant votre fichier XHTML
  • définir le src d'une image sur l'URL de données de ce SVG
  • drawImage sur la toile
  • définir les données de la zone de dessin pour cibler image.src

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

Quelques choses à noter

  • Le HTML à l'intérieur du SVG doit être XHTML
  • Pour des raisons de sécurité, l’URL de données SVG d’une image agit comme une étendue CSS isolée pour le code HTML, aucune source externe ne pouvant être chargée. Ainsi, une police Google, par exemple, doit être intégrée à l'aide d'un outil tel que celui-ci .
  • Même lorsque le code HTML contenu dans le fichier SVG dépasse la taille de l'image, il sera dessiné correctement sur le canevas. Mais la hauteur réelle ne peut pas être mesurée à partir de cette image .. Une solution à hauteur fixe fonctionnera très bien, mais une hauteur dynamique nécessitera un peu plus de travail. Le mieux est de restituer les données SVG dans une iframe (pour une portée CSS isolée) et d'utiliser la taille résultante pour le canevas.
19
Sjeiti

Oui. HTML2Canvas existe pour rendre HTML sur <canvas> (que vous pouvez ensuite utiliser comme image).

NOTE: Il y a un problème connu, cela ne fonctionnera pas avec SVG.

91
AKX

Puis-je recommander dom-to-image library, qui a été écrit uniquement pour résoudre ce problème (je suis le responsable).
Voici comment vous l’utilisez (un peu plus ici ):

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

Il y a beaucoup d'options et ils ont tous leurs avantages et leurs inconvénients. 

Option 1: Utilisez l'une des nombreuses bibliothèques disponibles

Avantages

  • La conversion est assez rapide la plupart du temps

Les inconvénients

  • Mauvais rendu
  • N'exécute pas javascript
  • Aucune prise en charge des fonctionnalités Web récentes (FlexBox, sélecteurs avancés, polices Web, dimensionnement de boîtes, requêtes multimédias, ...)
  • Parfois pas si facile à installer
  • Compliqué à l'échelle

Option 2: Utiliser PhantomJs et peut-être une bibliothèque de wrapper

Avantages

  • Exécuter Javascript
  • Tres rapide

Les inconvénients

  • Mauvais rendu
  • Aucune prise en charge des fonctionnalités Web récentes (FlexBox, sélecteurs avancés, polices Web, dimensionnement de boîtes, requêtes multimédias, ...)
  • Compliqué à l'échelle
  • Pas facile de le faire fonctionner s'il y a des images à charger ...

Option 3: utiliser Chrome Headless et peut-être une bibliothèque d'encapsuleurs

Avantages

  • Exécuter Javascript
  • Rendu presque parfait

Les inconvénients

  • Pas si facile d'avoir exactement le résultat souhaité concernant:
    • moment du chargement de la page
    • dimensions de la fenêtre
  • Compliqué à l'échelle
  • Assez lent et encore plus lent si le code HTML contient des liens externes

Option 4: utiliser une API

Avantages

  • Exécuter Javascript
  • Rendu presque parfait
  • Rapide lorsque les options de mise en cache sont correctement utilisées
  • L'échelle est gérée par les API
  • Chronométrage précis, fenêtre d'affichage, ...
  • La plupart du temps, ils offrent un plan gratuit

Les inconvénients

  • Pas gratuit si vous envisagez de les utiliser beaucoup

_ {Avertissement: je suis le fondateur d'ApiFlash. J'ai fait de mon mieux pour fournir une réponse honnête et utile.} _

36
Timothée Jeannin

Vous pouvez utiliser PhantomJS , qui est un pilote Webkit sans tête (le moteur de rendu de Safari et (jusqu’à récemment) chromé). Vous pouvez apprendre à faire une capture d'écran de pages ici . J'espère que cela pourra aider!

13
TheContrarian

Vous pouvez utiliser un outil HTML pour PDF tel que wkhtmltopdf. Et vous pouvez ensuite utiliser un outil PDF pour créer une image, comme imagemagick. Certes, ceci est côté serveur et un processus très compliqué ...

11
PinnyM

La seule bibliothèque que j'ai pu utiliser pour Chrome, Firefox et MS Edge était rasterizeHTML . Il produit une meilleure qualité que HTML2Canvas et est toujours pris en charge contrairement à HTML2Canvas.

Obtenir un élément et le télécharger au format PNG

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

Je ne m'attends pas à ce que ce soit la meilleure réponse, mais cela semblait assez intéressant pour être publié.

Ecrivez une application qui ouvre votre navigateur favori au document HTML souhaité, redimensionne correctement la fenêtre et prend une capture d'écran. Ensuite, supprimez les bordures de l'image.

5
John Fisher

Vous ne pouvez pas faire cela à 100% avec JavaScript.

Il y a un outil Qt Webkit out there, et une version de python . Si vous voulez le faire vous-même, j'ai eu du succès avec Cocoa:

[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];
}];

J'espère que cela t'aides!

2
Matt Melton

Installez Phantomjs

$ npm install phantomjs

Créez un fichier github.js avec le code suivant

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

Transmettez le fichier en argument à phantomjs

$ phantomjs github.js
1
Saurabh Saxena

Utilisez html2canvas. Incluez simplement le plug-in et la méthode d'appel pour convertir HTML en Canvas, puis téléchargez-le au format PNG.

        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

Vous pouvez certainement. L'API JavaScript de GrabzIt vous permet de capturer une div depuis une page Web comme celle-ci:

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

Où #features est l'ID de la div à capturer. Si vous vouliez convertir HTML en image. Vous pouvez utiliser cette technique:

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

Disclaimer J'ai construit cette API!

1
GrabzIt

Utilisez ce code, cela fonctionnera sûrement:

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

N'oubliez pas d'inclure le fichier Html2CanvasJS dans votre programme . https://html2canvas.hertzen.com/dist/html2canvas.js } _

0
Mohit Kulkarni

HtmlToImage.jar sera le moyen le plus simple de convertir un fichier HTML en image

Conversion de HTML en image à l'aide de Java

0
Ranjith rajavelu

Dessiner des objets DOM dans un canevas montre un moyen rapide de le faire.

Du point de vue des performances, cette méthode devrait être légère. Parce que le moteur de rendu svg et le moteur de rendu dom peuvent apparemment faire passer des tampons en arrière selon les besoins. Ce qui a du sens car c'est tout le code de base.

Je n'ai pas de points de repère à ce sujet, mais les documents MDN sont plutôt bien conservés, pas seulement pour le gecko. Je suppose donc que vous pouvez au moins savoir que les mauvaises performances sont un problème qui sera résolu à un moment donné.

0
Tamir Daniely

Je sais que c'est une question assez ancienne qui a déjà beaucoup de réponses, mais j'ai quand même passé des heures à essayer de faire ce que je voulais:

  • à partir d'un fichier HTML, générez une image (png) avec transparent background à partir de la ligne de commande

Avec Chrome headless (version 74.0.3729.157 à compter de cette réponse), il est en fait simple:

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

Explication de la commande:

  • vous exécutez Chrome à partir de la ligne de commande (indiqué ici pour le Mac, mais en supposant qu'il soit similaire sous Windows ou Linux)
  • --headless exécute Chrome sans l'ouvrir et se ferme une fois la commande terminée
  • --screenshot va capturer une capture d'écran (notez qu'il génère un fichier appelé screenshot.png dans le dossier où la commande est exécutée)
  • --window-size permet de ne capturer qu'une partie de l'écran (le format est --window-size=width,height)
  • --default-background-color=0 est le tour de magie qui demande à Chrome d’utiliser un transparent background, et non la couleur blanche par défaut.
  • enfin vous fournissez le fichier html (sous forme d'URL locale ou distante ...)
0
yan