网页中的iframe可以截图吗?

问题描述 投票:0回答:6

我正在尝试截取网页中 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 不起作用,是否有其他方法可以实现我想要做的事情?

如果需要更多信息,请告诉我。

任何帮助将不胜感激。

提前致谢

javascript html iframe screenshot html2canvas
6个回答
3
投票

如果您需要以编程方式进行捕获,您可以选择将 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/


2
投票

有一个解决方案,当你使用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
  });
}

1
投票

如果您只想截取屏幕截图,只需使用截图工具即可(但我想这不是您的情况)。

从编程的角度来看:

考虑 iframe 在您的网站内加载外部页面,而您对此没有控制权。加载的页面代码不是源代码的一部分,您几乎无法控制它以编程方式进行广泛的编辑/功能。

here所述,可以使用FF中iframe的

getScreenshot
方法。这可能对您有用,但我想这对于简单的场景可能有用,并且不能被视为用作功能的完整的跨浏览器兼容性解决方案。


1
投票

你不能,因为它们是单独的文档。实现这一目标的唯一方法是在打印之前操作页面的代码,以便 iframe 更大,但这必须手动完成,因为 iframe 的宽度和高度可能不是实际限制其大小的唯一页面元素。例如,iframe 可以位于其他几个具有固定大小的 div 标签内。您还需要知道 iframe 中显示的内容的高度和宽度,以便知道 iframe 的新尺寸有多大。


1
投票

在浏览器中并使用相同的方法ugyanakkor解释,dom-to-image-more现在支持同源和blob iframe支持(由我实现)。但它可能还没有被放入 npm 注册表;如果是这样,请将 dom-to-image-more.js 添加到您的代码中。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.