[英]How to render HTML pages as PNG/JPEG images on single click using URLs Tabs array in Javascript only?
我正在使用 Javascript 構建一個 chrome 擴展程序,它獲取打開的選項卡的 URL 並保存 html 文件,但 html 的問題是它不能在網頁上完全呈現圖像。 因此,我更改了代碼以循環選項卡的每個 URL,然后單擊 chrome 擴展程序的下載圖標自動將每個 html 頁面保存為圖像文件。 我已經研究了超過 2 天,但什么也沒發生。 請查看我的代碼文件並指導我。 我知道 nodejs 中有庫,但我想僅使用 chrome 擴展名對 jpeg/png maker 執行 html。
只有我沒有附加的圖標,我在這個擴展中使用過,我擁有的所有代碼和我嘗試過的popup.js
中的文本。
更新了 popup.js
文件popup.js
- 此文件具有獲取瀏覽器中打開的選項卡的所有 URL 的功能 window
// script for popup.html
window.onload = () => {
// var html2obj = html2canvas(document.body);
// var queue = html2obj.parse();
// var canvas = html2obj.render(queue);
// var img = canvas.toDataURL("image/png");
let btn = document.querySelector("#btnDL");
btn.innerHTML = "Download";
function display(){
// alert('Click button is pressed')
window.open("image/url");
}
btn.addEventListener('click', display);
}
chrome.windows.getAll({populate:true}, getAllOpenWindows);
function getAllOpenWindows(winData) {
var tabs = [];
for (var i in winData) {
if (winData[i].focused === true) {
var winTabs = winData[i].tabs;
var totTabs = winTabs.length;
console.log("Number of opened tabs: "+ totTabs);
for (var j=0; j<totTabs;j++) {
tabs.push(winTabs[j].url);
// Get the HTML string in the tab_html_string
tab_html_string = get_html_string(winTabs[j].url)
// get the HTML document of each tab
tab_document = get_html_document(tab_html_string)
console.log(tab_document)
let canvasref = document.querySelector("#capture");
canvasref.appendChild(tab_document.body);
html2canvas(document.querySelector("#capture")).then(canvasref => {
document.body.appendChild(canvasref)
var img = canvasref.toDataURL("image/png");
window.open(img)
});
}
}
}
console.log(tabs);
}
function get_html_document(tab_html_string){
/**
* Convert a template string into HTML DOM nodes
*/
var parser = new DOMParser();
var doc = parser.parseFromString(tab_html_string, 'text/html');
return doc;
}
function get_html_string(URL_string){
/**
* Convert a URL into HTML string
*/
let xhr = new XMLHttpRequest();
xhr.open('GET', URL_string, false);
try {
xhr.send();
if (xhr.status != 200) {
alert(`Error ${xhr.status}: ${xhr.statusText}`);
} else {
return xhr.response
}
} catch(err) {
// instead of onerror
alert("Request failed");
}
}
文件popup.html
- 此文件表示 chrome 瀏覽器搜索欄上的圖標和單擊功能
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<script src= './html2canvas.min.js'></script>
<script src= './jquery.min.js'></script>
<script src='./popup.js'></script>
<title>Capture extension</title>
<!--
- JavaScript and HTML must be in separate files: see our Content Security
- Policy documentation[1] for details and explanation.
-
- [1]: http://developer.chrome.com/extensions/contentSecurityPolicy.html
-->
</head>
<body>
<button id="btnDL"></button>
</body>
</html>
文件manifest.json
- 這個文件被 chrome 瀏覽器用來執行 chrome 擴展
{
"manifest_version": 2,
"name": "CIP screen capture",
"description": "One-click download for files from open tabs",
"version": "1.4.0.2",
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"downloads", "tabs", "<all_urls>"
],
"options_page": "options.html"
}
您可以使用庫html2canvas
呈現任何 html 元素,尤其是body
元素,並從生成的 canvas 中獲得您的圖像
<script type="text/javascript" src="https://github.com/niklasvh/html2canvas/releases/download/v1.0.0-rc.7/html2canvas.min.js"></script>
<script>
html2canvas(document.body).then(
(canvas) => {
var img = canvas.toDataURL("image/png");
}
);
</script>
您可以從任何公共 CDN 獲取 html2canvas,例如這個。 你不需要nodeJS。 或者直接來自原始 git 存儲庫
<script type="text/javascript" src="https://github.com/niklasvh/html2canvas/releases/download/v1.0.0-rc.7/html2canvas.min.js"></script>
您還可以將 canvas 保存為 blob
html2canvas(document.body).then(function(canvas) {
// Export canvas as a blob
canvas.toBlob(function(blob) {
// Generate file download
window.saveAs(blob, "yourwebsite_screenshot.png");
});
});
使用 vanilla JS 是可能的,我猜 vanilla 更有可能用於擴展,缺點是最終結果,當第 3 方庫我已經修復了 fonts 和樣式(html2canvas 或其他)時會遇到的問題。
所以,香草js,由於某種原因堆棧溢出片段不允許 window.open ,這里演示: https://jsfiddle.net/j67nqsme/
關於它是如何實施的幾句話:
免責聲明:我不會幫助您調試或找到問題的解決方案,它是使用 vanilla js 對您的問題的回答,從那里您決定使用什么或如何使用它。
源代碼如下:
<html>
<body>
<script>
function export1() {
const html = '<div style="color:red">this is <br> sparta </div>';
renderHtmlToImage(html, 800, 600, "image/png");
}
function export2() {
renderDocumentToImage(window.document, 800, 600, "image/png");
}
// format is: image/jpeg, image/png, image/svg+xml
function exportImage(base64data, width, height, format) {
var img = new Image();
img.onload = function () {
if ("image/svg+xml" == format) {
var w = window.open("");
w.document.write(img.outerHTML);
w.document.close();
}
else {
const canvas = document.createElement("Canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
var exportImage = new Image();
exportImage.onload = function () {
var w = window.open("");
w.document.write(exportImage.outerHTML);
w.document.close();
}
exportImage.src = canvas.toDataURL(format);
}
}
img.src = base64data;
}
// format is: image/jpeg, image/png, image/svg+xml
function renderHtmlToImage(html, width, height, format) {
var svgData = '<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="' + height + '">'
+ '<foreignObject width="100%" height="100%">'
+ html2SvgXml(html)
+ '</foreignObject>'
+ '</svg>';
var base64data = "data:image/svg+xml;base64," + btoa(svgData);
exportImage(base64data, width, height, format);
}
function renderDocumentToImage(doc, width, height, format) {
var svgData = '<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="' + height + '">'
+ '<foreignObject width="100%" height="100%">'
+ document2SvgXml(doc)
+ '</foreignObject>'
+ '</svg>';
var base64data = "data:image/svg+xml;base64," + btoa(svgData);
exportImage(base64data, width, height, format);
}
// plain html to svgXml
function html2SvgXml(html) {
var htmlDoc = document.implementation.createHTMLDocument('');
htmlDoc.write(html);
// process document
return document2SvgXml(htmlDoc);
}
// htmlDocument to
function document2SvgXml(htmlDoc) {
// Set the xmlns namespace
htmlDoc.documentElement.setAttribute('xmlns', htmlDoc.documentElement.namespaceURI);
// Get XML
var svcXml = (new XMLSerializer()).serializeToString(htmlDoc.body);
return svcXml;
}
</script>
<div>
<h3 style="color:blue">My Title</h3>
<div style="color:red">
My Text
</div>
<button onclick="export1()">Export Plain Html</button>
<button onclick="export2()">Export Entire Document</button>
</div>
</body>
</html>
有3種方法可以解決這個問題:
使用像HTML2Canvas這樣的 API 在客戶端 javascript 中渲染它。 它是隔離的,在瀏覽器中運行,但依賴於重新渲染,這可能會使捕獲的頁面的詳細信息出錯(請參閱H2C 的大多數問題)。 如果您只想要一個小預覽並且不介意奇怪的差異,那可能會很好。 還要小心,因為渲染速度很慢並且有些重量級 - 用戶可能會注意到大頁面的背景渲染,但等待圖像渲染也是如此。
使用運行 Chrome 的服務訪問該頁面,然后對其進行截圖。 你可以寫這個或者購買像Site-Shot這樣的服務來為你做。 這需要一項服務,該服務會產生成本,但可以保證渲染准確並確保用戶機器上的負載最小。
使用Chrome 選項卡捕獲 API來截取選項卡。 這可能是擴展的最佳選擇,但目前您只能捕獲當前活動選項卡。 captureOffscreenTab
即將推出,但目前僅在 Canary 后面有一個標志。
我推薦選項 3,因為當您完成組件時,您可以訪問新功能。 如果您需要盡快發布,您可以使用 1 或 2 作為短期解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.