HTMLを画像にレンダリングする


166

HTMLをPNGのような画像にレンダリングする方法はありますか?canvasでそれが可能であることは知っていますが、たとえばdivのような標準のhtml要素をレンダリングしたいと思います。


たとえば、ある種のユーザー支援を作成するため。残念ながら、それは不可能です(セキュリティ上の理由から?)。何かを行うには、PrintScreenを押すようにユーザーに要求する必要があります。
MaxArt、2012年


HTML / CSSを使用してロゴをデザインしたい。
マーティンデリル

4
@ ErnestFriedman-Hillは重複しません:あなたが言及した質問はjavaに固有のものです。
Martin Delille、

これは、HTMLを画像pngまたはjpeg形式に変換するためのステップバイステップチュートリアルです。codepedia.info
2016/02/

回答:


41

これはかなり古い質問であることは知っていますが、すでに多くの答えがありますが、それでも私が実際にやりたいことを実行するために何時間も費やしました。

  • HTMLファイルを指定すると、コマンドラインから背景が透明な(png)画像を生成します

Chromeヘッドレス(この応答ではバージョン74.0.3729.157)を使用すると、実際には簡単です。

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

コマンドの説明:

  • コマンドラインからChromeを実行します(ここではMacで示していますが、WindowsまたはLinuxでも同様です)
  • --headless Chromeを開かずに実行し、コマンドの完了後に終了します
  • --screenshotスクリーンショットをキャプチャします(screenshot.pngコマンドが実行されるフォルダに呼び出されるファイルを生成することに注意してください)
  • --window-size画面の一部のみをキャプチャすることを許可する(形式は--window-size=width,height
  • --default-background-color=0デフォルトの白い色ではなく、透明な背景を使用するようにChromeに指示する手品です
  • 最後に、htmlファイルを提供します(ローカルまたはリモートのURLとして...)

1
非常に素晴らしい!SVGでも動作します!最後にあなたの解決策に切り替えました!;-)
Martin Delille、

1
--screenshot='absolute\path\of\screenshot.png'私のために働いた
パラッシュ

コマンラインが働いた。これをプログラムでExpress jsから実行する場合は、どのように実行しますか?
Squaplレシピ

参考までに、manページのオプションについては触れていませんが、これはchromeでも機能します。
Robin Lashof-Regas

svgは私にとってsvgではありません...それはSVG拡張子を付けた単なるPNGです...ですので注意してください。
kristopolous

97

はい。HTML2Canvasは、HTMLをレンダリングするために存在します<canvas>(これをイメージとして使用できます)。

注:これはSVGでは機能しないという既知の問題があります。


おもしろそうですが、うまく動かせなかったので、ジョン・フィッシャーのソリューションを選びました。情報をありがとう、私は将来このプロジェクトを見ます!
マーティンデリル

@MartinDelille:ここに画像を作成するために、あなたはまた、クライアント側でそれをダウンロードすることができHTML2Canvasを使用しての記事 codepedia.info/2016/02/...
シンSatinder

3
dom-to-image(tsayenの回答を参照)は、正確な画像をレンダリングするためのはるかに優れた仕事をします。
JBE、2016年

3
この解決策は非常に遅い
hamboy75 2017年

3
別の問題、要素が非表示になっている場合、または別の要素の背後にある場合、これは機能しません
Yousef

91

この問題に対処するためだけに書かれたdom-to-imageライブラリをお勧めします(私はメンテナーです)。
以下にその使用方法を示します(詳細はこちら)。

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

2
これは素晴らしい!出力サイズを2倍にする方法はありますか?
cronoklee 2016

ありがとう!しかし、「サイズを2倍にする」とはどういう意味ですか?
tsayen 2016

2
最初に頭に浮かぶのは、イメージをSVGに(を使用してdomtoimage.toSvg)レンダリングしてから、キャンバス上で自分でレンダリングし、そのキャンバスの解像度でなんとかしてみてください。lib自体にある種のレンダリングオプションなどの機能を実装できるので、画像のサイズをピクセルで渡すことができます。必要な場合は、githubで問題を作成していただければ幸いです。
tsayen 2016

8
これはhtml2canvasよりはるかに優れています。ありがとう。
c.hughes

1
@Subhoこれは、base64でエンコードされたデータを含むURLを含む文字列です
tsayen

66

多くのオプションがあり、それらはすべて長所と短所があります。

オプション1:多くの利用可能なライブラリの1つを使用する

長所

  • ほとんどの場合、変換はかなり高速です

短所

  • 悪いレンダリング
  • JavaScriptを実行しません
  • 最近のWeb機能(FlexBox、Advanced Selectors、Webfonts、Box Sizing、Media Queriesなど)はサポートされていません
  • インストールが簡単でない場合があります
  • スケールが複雑

オプション2:PhantomJsとラッパーライブラリを使用する

長所

  • Javascriptを実行する
  • かなり速いです

短所

  • 悪いレンダリング
  • 最近のWeb機能(FlexBox、Advanced Selectors、Webfonts、Box Sizing、Media Queriesなど)はサポートされていません
  • スケールが複雑
  • ロードする画像がある場合、動作させるのはそれほど簡単ではありません...

オプション3:Chromeヘッドレスとラッパーライブラリを使用する

長所

  • Javascriptを実行する
  • ほぼ完璧なレンダリング

短所

  • 次の点に関して希望どおりの結果を得るのは簡単ではありません。
    • ページ読み込みタイミング
    • ビューポートの寸法
  • スケールが複雑
  • htmlに外部リンクが含まれている場合、かなり遅く、さらに遅くなる

オプション4:APIを使用する

長所

  • Javascriptを実行する
  • ほぼ完璧なレンダリング
  • キャッシュオプションを正しく使用すると高速
  • スケールはAPIによって処理されます
  • 正確なタイミング、ビューポート、...
  • ほとんどの場合、彼らは無料プランを提供しています

短所

  • たくさん使うつもりなら無料ではない

開示:私はApiFlashの創設者です。私は正直で有用な答えを提供するために最善を尽くしました。


2
可能な解決策がたくさんある詳細な回答をありがとう
bszom 2018年

wkhtmltoimage / pdfはJavaScriptレンダリングをサポートしています。javascriptの遅延を設定するか、wkhtmlに特定のwindow.statusをチェックさせることができます(jsの処理が完了していることがわかっている場合は、javascriptで設定できます)
Daniel Z.

PhantomJSは、Googleマップのような動的なものをサポートしています。これは、ディスプレイが接続されていない、完全なWebブラウザーです。ただし、Googleマップが地理のタイルを読み込むのを少し待つ必要があります(私は500ミリ秒待って、ユーザーが遅延を変更できるようにします-十分でない場合は、タイルをキャッシュするため、時間を増やすことなくもう一度実行しても問題ありません)。
Ladislav Zima

50

ここでのすべての回答はサードパーティのライブラリを使用していますが、HTMLを画像にレンダリングすることは、純粋なJavaScriptでは比較的簡単です。そこさえしたことについての記事 MDNのキャンバスセクションに。

トリックはこれです:

  • XHTMLを含むforeignObjectノードでSVGを作成する
  • 画像のソースをそのSVGのデータURLに設定します
  • drawImage キャンバスに
  • キャンバスデータをターゲット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()
}

注意すべきいくつかのこと

  • SVG内のHTMLはXHTMLである必要があります
  • セキュリティ上の理由から、画像のデータURLとしてのSVGは、外部ソースをロードできないため、HTMLの分離されたCSSスコープとして機能します。したがって、たとえばGoogleフォントは、このようなツールを使用してインライン化する必要があります。
  • SVG内のHTMLが画像のサイズを超える場合でも、キャンバスに正しく描画されます。しかし、その画像から実際の高さを測定することはできません。高さが固定のソリューションは問題なく機能しますが、動的な高さはもう少し作業が必要になります。最善の方法は、SVGデータをiframeにレンダリングし(分離されたCSSスコープの場合)、結果のサイズをキャンバスに使用することです。

いいね!外部ライブラリの依存関係を削除することは、確かに良い方法です。私は受け入れた回答を変更しました:-)
Martin Delille '31 / 10/31

その記事はもうありません。
MSC

2
素晴らしい答えですが、HTMLとWeb APIの最新技術についてコメントします。これは、通常、何かが背後に引き出されているように見えます。すべての機能は技術的には存在しますが、類似した奇妙なコードパスの配列(意図されていない)の背後に公開されています。適切に設計されたAPIから期待できるような明確さはありません。平易に言えば、ブラウザがDocumentaをラスター(例:)にレンダリングできるようにするのは簡単なことですが、誰もそれCanvasを標準化しようとはしなかったので、上に示したような狂気に頼らなければなりません(この作者に不快感はありません)コード)。
2018年

1
この回答stackoverflow.com/questions/12637395/…は、かなり遠くまで行けることを示しているようです。MozillaとChromeには無制限のデータuriがあり、現在のIEでも4GBを許可しています。しかし、これはテストするのに適しています。
Sjeiti

3
-後で簡単なテストをいくつか行います-jsfiddle.net/Sjeiti/pcwudrmc/75965 Chrome、Edge、Firefoxの幅の高さが少なくとも10,000ピクセルに達します(この場合)。 8MBの。厳密なテストはしていませんが、ほとんどのユースケースでは十分です。
Sjeiti

13

ヘッドレスWebキット(サファリのレンダリングエンジンと(最近まで)クロム)ドライバーであるPhantomJSを使用できます。ページの画面キャプチャーの方法については、こちらをご覧ください。お役に立てば幸いです。


この手法はうまくいきます。ただし、コメントから2年が経過しました。PhantomJSよりも高速に動作するものに遭遇しましたか?私の経験では、画像生成は通常、ファントムで2〜5秒かかります。
Brian Webster

ヘッドレスChromeが可能になりました。高速かどうかはわかりませんが、正確なスクリーンショットが必要な場合は、この方法が適しています。
Josh Maag 2017

11

wkhtmltopdfのようなHTMLからPDFへのツールを使用できます。そして、あなたはPDFをimagemagickのような画像ツールに使うことができます。確かにこれはサーバー側であり、非常に複雑なプロセスです...


12
または、wkhtmltopdfのイメージ兄弟であるwkhtmltoimageを実行することもできます。
Roman Starkov、2015

1
このライブラリはのためのものNode.jsです。単純なフロントエンドはどうですか?
ヴラド

9

Chrome、Firefox、MS Edgeで使用できる唯一のライブラリはrasterizeHTMLでした。HTML2Canvasよりも優れた品質を出力し、HTML2Canvasとは異なりサポートされています。

Elementの取得と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);
            }
     });

2
IEでは動作しません。 rasterizeHTMLの制限
Boban Stojanovski

@vabanagasこのための単一ファイルのJavaScriptはありますか?
Mahdi Khalili

この変更は私に大いに役立ちました:rasterizeHTML.drawHTML(node.innerHTML, canvas) ノードでinnerHTMLを呼び出すことに注意してください
Sep GH

5

html2canvasを使用してプラグインを含め、メソッドを呼び出してHTMLをCanvasに変換し、画像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();
        });

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


4

これが最良の答えであるとは思いませんが、投稿するには面白そうだったようです。

お気に入りのブラウザーで目的のHTMLドキュメントを開き、ウィンドウのサイズを適切に設定し、スクリーンショットを撮るアプリを作成します。次に、画像の境界を削除します。


4

このコードを使用すると、確実に機能します。

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

プログラムにHtml2CanvasJSファイルを含めることを忘れないでください。 https://html2canvas.hertzen.com/dist/html2canvas.js


2

JavaScriptだけでこれを100%正確に行うことはできません。

Qt Webkit ツールPythonバージョンがあります。あなたがそれを自分でやりたいのなら、私はココアで成功しました:

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

お役に立てれば!


上記の迅速なバージョンはありますか?または可能であれば、書き直していただけますか?
ssh

レンダリングしているwebViewをロードするために使用するコードを共有していただけませんか?これは私のサムネイルレンダラーにとって有望なアプローチのようです。ありがとう!
デイブ

1

phantomjsをインストールする

$ npm install phantomjs

次のコードでファイルgithub.jsを作成します

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

ファイルを引数としてphantomjsに渡します

$ phantomjs github.js


-3

あなたはできる参照の追加 HtmlRendererをプロジェクトに、次の操作を行い、

string htmlCode ="<p>This is a sample html.</p>";
Image image = HtmlRender.RenderToImage(htmlCode ,new Size(500,300));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.