HTMLをPNGのような画像にレンダリングする方法はありますか?キャンバスで可能であることは知っていますが、たとえばdivのような標準のhtml要素をレンダリングしたいと思います。
18 に答える
多くのオプションがあり、それらはすべて長所と短所があります。
オプション1:APIを使用する
- ApiFlash(クロムベース)
- EvoPDF(htmlのオプションがあります)
- グラブジット
- HTML/CSSからImageAPIへ
- ..。
長所
- Javascriptを実行する
- ほぼ完璧なレンダリング
- キャッシュオプションが正しく使用されている場合は高速
- スケールはAPIによって処理されます
- 正確なタイミング、ビューポート、..。
- ほとんどの場合、彼らは無料プランを提供しています
短所
- あなたがそれらをたくさん使うことを計画しているなら無料ではありません
オプション2:利用可能な多くのライブラリの1つを使用する
- dom-to-image
- wkhtmltoimage(wkhtmltopdfツールに含まれています)
- IMGKit(ruby用およびwkhtmltoimageに基づく)
- imgkit(python用およびwkhtmltoimageに基づく)
- python-webkit2png
- ..。
長所
- ほとんどの場合、変換は非常に高速です
短所
- 悪いレンダリング
- javascriptを実行しません
- 最近のWeb機能(FlexBox、Advanced Selectors、Webfonts、Box Sizing、Media Queriesなど)はサポートされていません。
- インストールが簡単でない場合もあります
- スケールが複雑
オプション3:PhantomJsとおそらくラッパーライブラリを使用する
- PhantomJs
- node-webshot(PhantomJのjavascriptラッパーライブラリ)
- ..。
長所
- Javascriptを実行する
- かなり速いです
短所
- 悪いレンダリング
- 最近のWeb機能(FlexBox、Advanced Selectors、Webfonts、Box Sizing、Media Queriesなど)はサポートされていません。
- スケールが複雑
- ロードする画像がある場合、それを機能させるのはそれほど簡単ではありません...
オプション4:Chromeヘッドレスとおそらくラッパーライブラリを使用する
- Chromeヘッドレス
- chrome-devtools-protocol
- Puppeteer(Chromeヘッドレス用のjavascriptラッパーライブラリ)
- ..。
長所
- Javascriptを実行する
- ほぼ完璧なレンダリング
短所
- 以下に関して、正確に望ましい結果を得るのはそれほど簡単ではありません。
- ページの読み込みタイミング
- ビューポートの寸法
- スケールが複雑
- HTMLに外部リンクが含まれている場合は、かなり遅くなり、さらに遅くなります
開示:私はApiFlashの創設者です。私は正直で有用な答えを提供するために最善を尽くしました。
はい。HTML2Canvasは、HTMLをレンダリングするために存在します<canvas>
(画像として使用できます)。
注:これはSVGでは機能しないという既知の問題があります
この問題に対処するためだけに作成された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);
});
ここでのすべての回答はサードパーティのライブラリを使用していますが、HTMLを画像にレンダリングすることは純粋なJavascriptでは比較的簡単です。MDNのキャンバスセクションにもそれに関する記事がありました。
トリックはこれです:
- XHTMLを含むforeignObjectノードでSVGを作成します
- 画像のsrcをその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スコープの場合)、結果のサイズをキャンバスに使用することです。
私はこれがすでに多くの答えを持っているかなり古い質問であることを知っています、それでも私はまだ私がしたいことを実際にやろうとして何時間も費やしました:
- 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として...)提供します。
Chrome、Firefox、MSEdgeで動作するようになった唯一のライブラリは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);
}
});
wkhtmltopdfのようなHTMLからPDFへのツールを使用できます。そして、PDFを使用してimagemagickのような画像ツールを作成できます。確かに、これはサーバー側であり、非常に複雑なプロセスです...
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/
このコードを使用すると、確実に機能します。
<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
非常に興味深いと思ったSjeitiの回答を読みました。ここでは、ほんの数行のプレーンなJavaScript行で画像にHTMLをレンダリングできます。
もちろん、この方法の制限に注意する必要があります(彼の回答でそれらのいくつかについて読んでください)。
ここで私は彼のコードをさらにいくつかのステップに進めました。
SVG画像はベクターグラフィックスであるため、原則として無限の解像度を持っています。しかし、Sjeitiのコードが生成した画像の解像度が高くないことに気付いたかもしれません。これは、SVGイメージをcanvas-elementに転送する前にスケーリングすることで修正できます。これは、以下に示す2つの(実行可能な)サンプルコードの最後の1つで行いました。そのコードに実装したもう1つのことは、最後のステップ、つまりPNGファイルとして保存することです。すべてを完了するためだけに。
そこで、実行可能な2つのコードスニペットを示します。
最初のものは、SVGの無限の解像度を示しています。それを実行し、ブラウザでズームインして、ズームインしても解像度が低下しないことを確認します。
実行できるスニペットでは、バッククォートを使用して、レンダリングされるHTMLをより明確に確認できるように、改行付きのいわゆるテンプレート文字列を指定しました。ただし、それ以外の場合、そのHTMLが1行以内にあると、コードは次のように非常に短くなります。
const body = document.getElementsByTagName('BODY')[0];
const img = document.createElement('img')
img.src = 'data:image/svg+xml,' + encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;"><style>em {color:red;}.test {color:blue;}</style>What you see here is only an image, nothing else.<br /><br /><em>I</em> really like <span class="test">cheese.</span><br /><br />Zoom in to check the resolution!</div></foreignObject></svg>`);
body.appendChild(img);
ここでは、実行可能なスニペットとして提供されます。
const body = document.getElementsByTagName('BODY')[0];
const img = document.createElement('img')
img.src = 'data:image/svg+xml,' + encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;">
<style>
em {
color:red;
}
.test {
color:blue;
}
</style>
What you see here is only an image, nothing
else.<br />
<br />
<em>I</em> really like <span class="test">cheese.</span><br />
<br />
Zoom in to check the resolution!
</div>
</foreignObject>
</svg>
`);
body.appendChild(img);
ズームインして、SVGの無限の解像度を確認します。
以下の次の実行可能ファイルは、前述の2つの追加手順、つまり最初にSVGをスケーリングして解像度を向上させ、次にPNG画像として保存する手順を実装するものです。
window.addEventListener("load", doit, false)
var canvas;
var ctx;
var tempImg;
function doit() {
const body = document.getElementsByTagName('BODY')[0];
const scale = document.getElementById('scale').value;
let trans = document.getElementById('trans').checked;
if (trans) {
trans = '';
} else {
trans = 'background-color:white;';
}
let source = `
<div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;${trans}">
<style>
em {
color:red;
}
.test {
color:blue;
}
</style>
What you see here is only an image, nothing
else.<br />
<br />
<em>I</em> really like <span class="test">cheese.</span><br />
<br />
<div style="text-align:center;">
Scaling:
<br />
${scale} times!
</div>
</div>`
document.getElementById('source').innerHTML = source;
canvas = document.createElement('canvas');
ctx = canvas.getContext('2d');
canvas.width = 200*scale;
canvas.height = 200*scale;
tempImg = document.createElement('img');
tempImg.src = 'data:image/svg+xml,' + encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" width="${200*scale}" height="${200*scale}">
<foreignObject
style="
width:200px;
height:200px;
transform:scale(${scale});
"
>` + source + `
</foreignObject>
</svg>
`);
}
function saveAsPng(){
ctx.drawImage(tempImg, 0, 0);
var a = document.createElement('a');
a.href = canvas.toDataURL('image/png');
a.download = 'image.png';
a.click();
}
<table border="0">
<tr>
<td colspan="2">
The claims in the HTML-text is only true for the image created when you click the button.
</td>
</tr>
<tr>
<td width="250">
<div id="source" style="width:200px;height:200px;">
</div>
</td>
<td valign="top">
<div>
In this example the PNG-image will be squarish even if the HTML here on the left is not exactly squarish. That can be fixed.<br>
To increase the resolution of the image you can change the scaling with this slider.
<div style="text-align:right;margin:5px 0px;">
<label style="background-color:#FDD;border:1px solid #F77;padding:0px 10px;"><input id="trans" type="checkbox" onchange="doit();" /> Make it transparent</label>
</div>
<span style="white-space:nowrap;">1<input id="scale" type="range" min="1" max="10" step="0.25" value="2" oninput="doit();" style="width:150px;vertical-align:-8px;" />10 <button onclick="saveAsPng();">Save as PNG-image</button></span>
</div>
</td>
</tr>
</table>
さまざまなスケーリングを試してください。たとえば、スケーリングを10に設定すると、生成されたPNG画像で非常に優れた解像度が得られます。また、必要に応じてPNG画像を透明にするためのチェックボックスという機能を少し追加しました。
知らせ:
このスクリプトをStackOverflowで実行すると、ChromeとEdgeで[保存]ボタンが機能しなくなります。理由はこのhttps://www.chromestatus.com/feature/5706745674465280です。
したがって、このスニペットはhttps://jsfiddle.net/7gozdq5v/にも配置しており、これらのブラウザーで機能します。
JavaScriptだけでは、これを100%正確に行うことはできません。
そこにはQtWebkitツールと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];
}];
お役に立てれば!
これが最良の答えになるとは思いませんが、投稿するのに十分興味深いようでした。
お気に入りのブラウザを目的のHTMLドキュメントに開き、ウィンドウのサイズを適切に設定し、スクリーンショットを撮るアプリを作成します。次に、画像の境界線を削除します。
これが私がしたことです。
注:コードについては、App.jsを確認してください。
あなたがそれを好きなら、あなたは星を落とすことができます。✌️
更新:
import * as htmlToImage from 'html-to-image';
import download from 'downloadjs';
import logo from './logo.svg';
import './App.css';
const App = () => {
const onButtonClick = () => {
var domElement = document.getElementById('my-node');
htmlToImage.toJpeg(domElement)
.then(function (dataUrl) {
console.log(dataUrl);
download(dataUrl, 'image.jpeg');
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
};
return (
<div className="App" id="my-node">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a><br></br>
<button onClick={onButtonClick}>Download as JPEG</button>
</header>
</div>
);
}
export default App;
私もこの問題に頭を悩ませています。そして、私はこれがあなたの問題の最良の解決策であると思いました
javascriptのライブラリを使用html-to-image
してHTMLコードを画像に変換できます
npm installhtml-to-image
HTMLコード
<div>
<div id="capture">
<p>
<span>Heading Of Image</span><br></br>
<span>This is color Image</span><br></br>
<img src="Your/ImagePath/ifany.jpg" width="100%" />
<span>Footer Of the Image</span>
</p>
</div>
<h2>Generated Image</h2>
<div id="real">
</div></div>
Javascriptコード
var htmlToImage = require('html-to-image');
var node = document.getElementById('capture');
htmlToImage.toJpeg(node, { quality: 1, backgroundColor: "#FFFFFF", height: node.clientHeight, width: node.clientWidth })
.then(function (dataUrl) {
var img = new Image();
img.src = dataUrl;
var div = document.getElementById("real")
div.appendChild(img)
})
.catch(function (error) {
console.error('oops, something went wrong!', error);
});
この例では、<div>
タグwhereで画像を表示できますid = 'real'
。これで、画像の保存とダウンロードまたはアップロードのオプションをコードに追加できます。
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
HtmlToImage.jarは、HTMLを画像に変換する最も簡単な方法です。
プロジェクトに参照 HtmlRendererを追加して、次の操作を行うことができます。
string htmlCode ="<p>This is a sample html.</p>";
Image image = HtmlRender.RenderToImage(htmlCode ,new Size(500,300));