web-dev-qa-db-ja.com

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

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

126
Martin Delille

ここでのすべての答えはサードパーティ製のライブラリを使用していますが、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フォントは this one のようなツールを使用してインライン化する必要があります。
  • SVG内のHTMLが画像のサイズを超えた場合でも、キャンバスに正しく描画されます。しかし、実際の高さはその画像からは測定できません。高さを固定したソリューションではうまく機能しますが、動的な高さではもう少し作業が必要になります。最善の方法は、SVGデータをiframe(分離されたCSSスコープ用)にレンダリングし、その結果のサイズをキャンバスに使用することです。
33
Sjeiti

はい。 HTML2Canvas はHTMLを<canvas>に描画するために存在します(これを画像として使うことができます)。

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

93
AKX

dom-to-image libraryをお勧めします。これはもっぱらこの問題に対処するために書かれたものです(私はメンテナです)。
これがその使い方です(もう少し here ):

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

たくさんの選択肢があり、それらはすべて長所と短所があります。

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

長所

  • ほとんどの場合、変換は非常に高速です。

短所

  • 悪いレンダリング
  • Javascriptを実行しません
  • 最近のWeb機能はサポートされていません(FlexBox、アドバンストセレクタ、Webフォント、ボックスサイズ、Media Queriesなど)。
  • 時にはそれほど簡単ではない
  • 縮尺が複雑

オプション2:PhantomJとおそらくラッパーライブラリを使う

長所

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

短所

  • 悪いレンダリング
  • 最近のWeb機能はサポートされていません(FlexBox、アドバンストセレクタ、Webフォント、ボックスサイズ、Media Queriesなど)。
  • 縮尺が複雑
  • ロードする画像がある場合、それを機能させるのはそれほど簡単ではありません.

オプション3:Chrome Headlessとおそらくラッパーライブラリを使う

長所

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

短所

  • 以下について正確に望ましい結果を得ることはそれほど簡単ではありません。
    • ページ読み込みタイミング
    • ビューポートの寸法
  • 縮尺が複雑
  • HTMLに外部リンクが含まれている場合、かなり遅くなり、さらに遅くなります。

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

長所

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

短所

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

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

38

あなたは PhantomJS を使うことができました。これはヘッドレスWebキット(Safariのレンダリングエンジンと(最近まで)chrome)ドライバです。あなたはページのスクリーンキャプチャをする方法を学ぶことができます ここ 。それが役立つことを願っています!

13
TheContrarian

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

11
PinnyM

私がChrome、Firefox、そしてMS Edgeで動かせた唯一のライブラリは rasterizeHTML でした。 HTML2Canvasよりも高品質の出力が得られ、HTML2Canvasとは異なりまだサポートされています。

要素を取得して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);
            }
     });
8
vabanagas

これが最善の答えになるとは思わないが、投稿するのに十分興味深いものと思われた。

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

5
John Fisher

html2canvasを使用すると、HTMLをキャンバスに変換するためのプラグインとメソッドの呼び出しが含まれ、イメージ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 /

2
Code Spy

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

Qt Webkit ツールアウト があり、 pythonバージョン があります。あなたがあなた自身でそれをやりたいならば、私は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];
}];

お役に立てれば!

2
Matt Melton

私はこれが非常に古い質問であることを知っています。それはすでにたくさんの答えを持っています、それでも私はまだ私が欲しいものを実際にやろうとすることに何時間も費やしました:

  • 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として)。
2
yan

このコードを使ってください、確かにうまくいくでしょう:

<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

1
Mohit Kulkarni

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
1
Saurabh Saxena

あなたは確かにできます。 GrabzItのJavaScript API あなたはこのようなウェブページからdivをキャプチャすることができます:

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

#featuresはキャプチャするdivのIDです。 HTMLを画像に変換したい場合あなたはこのテクニックを使うことができます:

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

免責事項このAPIを構築しました!

1
GrabzIt

HtmlToImage.jarは、htmlを画像に変換する最も簡単な方法です

Javaを使用してHTMLを画像に変換する

0

DOMオブジェクトをキャンバスに描く はそのための簡単な方法を示しています。

パフォーマンスの観点からは、この方法は簡単なはずです。 svgレンダラーとdomレンダラーは、明らかに必要に応じてバッファをやり取りできるためです。これはすべて中核的なコードなので、これは理にかなっています。

ベンチマークはありませんが、MDN文書は、geckoだけでなく、かなりよく管理されています。だから私はあなたが少なくとも悪いパフォーマンスがいくつかの時点で対処される問題であることを知ることができると思います。

0
Tamir Daniely