我正在尝试截取网页中 iframe 的屏幕截图。 在我的特定情况下,iframe 包含我的一位客户商店的街景视图。 据我搜索和阅读,我没有找到任何解决方案。
我知道有像
Html2Canvas
和 Canvas2Image
这样的 JavaScript 库,但它们无法捕获 iframe。
这里是我正在研究的小提琴。
这些库适用于除 iframe 之外的每个 HTML 元素。
这是小提琴的 JavaScript:
$(function() {
$("#btnSave").click(function() {
html2canvas($("#widget"), {
onrendered: function(canvas) {
var context=canvas.getContext("2d"); // returns the 2d context object
// Convert and download as image
theCanvas = canvas;
document.body.appendChild(canvas);
// Convert and download as image
Canvas2Image.saveAsPNG(canvas);
$("#img-out").append(canvas);
}
});
});
});
是否存在其他捕获 iframe 的方法? 有没有付费的第三方服务可以做到这一点?
如果 iframe 不起作用,是否有其他方法可以实现我想要做的事情?
如果需要更多信息,请告诉我。
任何帮助将不胜感激。
提前致谢
如果您需要以编程方式进行捕获,您可以选择将 NodeJS 与 puppeteer 一起使用,puppeteer 是一个使用 chromium 来模拟 Web 浏览器的库。我给你举个截屏的例子:
const puppeteer = require('puppeteer');
async function run() {
let browser = await puppeteer.launch({ headless: false });
let page = await browser.newPage();
await page.goto('https://www.scrapehero.com/');
await page.screenshot({ path: './image.jpg', type: 'jpeg' });
await page.close();
await browser.close();
}
run();
这是我得到它的来源: https://www.scrapehero.com/how-to-take-screenshots-of-a-web-page-using-puppeteer/
有一个解决方案,当你使用html2canvas时,输入变量必须是一个HTMLElement,然后它才会创建屏幕截图。旧浏览器也支持它(如 IE9),请查看文档:https://html2canvas.hertzen.com/documentation.html
import html2canvas from 'html2canvas';
screenShot() {
const iframe = document.getElementsByTagName('iframe');
const screen = iframe[0]?.contentDocument?.body;
html2canvas(screen)
.then((canvas) => {
const base64image = canvas.toDataURL('image/png');
// Do something with the image
});
}
如果您只想截取屏幕截图,只需使用截图工具即可(但我想这不是您的情况)。
从编程的角度来看:
考虑 iframe 在您的网站内加载外部页面,而您对此没有控制权。加载的页面代码不是源代码的一部分,您几乎无法控制它以编程方式进行广泛的编辑/功能。
如here所述,可以使用FF中iframe的
getScreenshot
方法。这可能对您有用,但我想这对于简单的场景可能有用,并且不能被视为用作功能的完整的跨浏览器兼容性解决方案。
你不能,因为它们是单独的文档。实现这一目标的唯一方法是在打印之前操作页面的代码,以便 iframe 更大,但这必须手动完成,因为 iframe 的宽度和高度可能不是实际限制其大小的唯一页面元素。例如,iframe 可以位于其他几个具有固定大小的 div 标签内。您还需要知道 iframe 中显示的内容的高度和宽度,以便知道 iframe 的新尺寸有多大。
在浏览器中并使用相同的方法ugyanakkor解释,dom-to-image-more现在支持同源和blob iframe支持(由我实现)。但它可能还没有被放入 npm 注册表;如果是这样,请将 dom-to-image-more.js 添加到您的代码中。
如果 iframe 来自外部源,您将无法访问内容,因此 html2canvas 等解决方案将不起作用。
我结束了使用Screen Capture API,这是唯一的解决方案。 缺点是用户必须授予 API 访问权限,并选择他想要捕获的正确选项卡。
这里的技巧是仅捕获屏幕中的特定元素。我将屏幕截图按钮放置在与 iframe 相同的 div 内的绝对位置,因此它将具有相同的起始 x 和 y 坐标。您可以将按钮移动到其他位置并将位移添加到drawImage。
这是一个片段:
let button = document.querySelector("#screenshotButton");
let iframe = document.querySelector("#screenshotIframe");
button.addEventListener("mouseup", async(event) => {
const buttonRect = button.getBoundingClientRect();
const iFrameRect = iframe.getBoundingClientRect();
// compute where do we click inside the button
const diffX = event.clientX - buttonRect.x;
const diffY = event.clientY - buttonRect.y;
// Determine the fixed screen iframe coordinates
const iFrameScreenX = event.screenX - diffX;
const iFrameScreenY = event.screenY - diffY;
// Create our temporary media elements
const video = document.createElement("video");
video.width = iFrameRect.width;
video.height = iFrameRect.height;
const canvas = document.createElement("canvas");
canvas.width = iFrameRect.width;
canvas.height = iFrameRect.height;
const context = canvas.getContext("2d");
if (!context) return;
// Ratio between device pixels and css pixels
const ratio = window.devicePixelRatio;
try {
const captureStream = await navigator.mediaDevices.getDisplayMedia();
video.srcObject = captureStream;
video.onloadeddata = () => {
context.drawImage(
video,
iFrameScreenX * ratio - window.screenX * ratio,
iFrameScreenY * ratio - window.screenY * ratio,
iFrameRect.width * ratio,
iFrameRect.height * ratio,
0,
0,
iFrameRect.width,
iFrameRect.height,
);
captureStream.getTracks().forEach((track) => track.stop());
canvas.toBlob((blob) => {
// save your blob here
// const formData = new FormData();
// formData.append("file", blob ?? "");
console.log(blob);
}, "image/jpeg");
};
} catch (err) {
console.error("Error during screenshot : " + err);
}
});
<div>
<button style="position: absolute;" id="screenshotButton">
Shot
</button>
<iframe title="screenshotIframe" id="screenshotIframe" src="https://www.orpha.net" width="100%" height="100%"></iframe>
</div>