【问题标题】:Firefox Addon API for Taking Screenshot用于截屏的 Firefox 插件 API
【发布时间】:2014-08-15 18:55:25
【问题描述】:

我正在寻找 Firefox 插件 api 来截取文档可见区域的屏幕截图。

Chrome 和 Safari 都有 api 来实现这一点。他们非常快。 我找不到任何特定于 Firefox 的内容。

我在How do I use the canvas drawWindow function in an addon created using the addon sdk? 找到了一种解决方法,但该解决方案采用包含滚动条的整页屏幕截图(文档的隐藏部分)。此解决方案有 2 个问题;

1-如果页面长滚动,完成截图过程需要很长时间。因为它使用的是基于画布的绘图。

2- 我想获取文档可见区域的屏幕截图,而不是整个文档。

有什么解决方法吗?

谢谢。

【问题讨论】:

  • 有很多 Firefox 插件可以做截图。下载 XPI 存档并查看源代码,这将帮助您入门。
  • drawWindow 是我知道的唯一方法。您可以提供第二个和第三个参数,即 x 和 y 来开始绘图,第四个和第五个参数告诉要绘制多少宽度和高度。如果您只提供窗口的第一个参数,那么它将绘制整个内容。所以提供第 2、3、4 和 5 个,等于 window.scrollTop + window.screenHeight 和 window.scrollLeft + window.screenWidth。 (注意:我猜到了这些窗口滚动属性,所以你可能需要查找正确的)
  • @Teoman Shipahi 你是怎么做到的?我看不懂代码

标签: firefox canvas firefox-addon screenshot firefox-addon-sdk


【解决方案1】:

使用 SDK,您可以执行以下操作:

const { window: { document } } = require('sdk/addon/window');
const { getTabContentWindow, getActiveTab } = require('sdk/tabs/utils');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');

const canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
document.documentElement.appendChild(canvas);

function captureTab(tab=getActiveTab(getMostRecentBrowserWindow())) {
  let contentWindow = getTabContentWindow(tab);

  let w = contentWindow.innerWidth;
  let h = contentWindow.innerHeight;
  let x = contentWindow.scrollX;
  let y = contentWindow.scrollY;

  canvas.width = w;
  canvas.height = h;

  let ctx = canvas.getContext('2d');

  ctx.drawWindow(contentWindow, x, y, w, h, '#000');
  return canvas.toDataURL();
}

这应该只占用可见区域。默认情况下,它会抓取活动选项卡,但您可以传递任何其他选项卡——因为它被设计为低级 API,它需要一个原生选项卡,而不是 SDK 选项卡。 您可以放入一个模块并仅导出 captureTab 函数。

编辑:e10s 版本

正如 Ian Bicking 在评论中指出的那样,上面的代码目前与带有 e10s 的 Firefox 不兼容。解决此问题的一种简单方法是在我们要捕获屏幕截图的同一文档和内容进程中创建一个临时画布:

const { getTabContentWindow, getActiveTab } = require('sdk/tabs/utils');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');

function captureTab(tab=getActiveTab(getMostRecentBrowserWindow())) {
  let contentWindow = getTabContentWindow(tab);
  let { document } = contentWindow;

  let w = contentWindow.innerWidth;
  let h = contentWindow.innerHeight;
  let x = contentWindow.scrollX;
  let y = contentWindow.scrollY;

  let canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');

  canvas.width = w;
  canvas.height = h;

  let ctx = canvas.getContext('2d');

  ctx.drawWindow(contentWindow, x, y, w, h, '#000');

  let dataURL = canvas.toDataURL();

  canvas = null;

  return dataURL;
}

这适用于 e10s 和 no-e10s FF 版本;与上一个相比的缺点是每次我们想要截屏时都会创建一个画布,但我认为是可以接受的。

【讨论】:

  • 非常好的解决方案,易于复制粘贴,我喜欢那些。
  • 你能在 sdk 1.17 视图中告诉我这个吗?
  • @abhilash 不确定您对“视图”的含义。你能详细说明一下吗?这也应该适用于 1.17。
  • 请注意,这不适用于 e10s(多进程):你会得到一个令人困惑的错误:TypeError: Argument 1 of CanvasRenderingContext2D.drawWindow does not implement interface Window 我认为这是因为窗口对象只是一个代理,而这一切都必须在其中运行某种框架脚本。不幸的是,我还没有弄清楚如何从 Jetpack/Addon-SDK 制作框架脚本。 ctx.drawWindow 在 contentScripts 中不可用。
  • 绝对正确;此代码是为 FF 之前的 e10 制作的。我也用 e10s 的解决方法更新了答案。谢谢。
【解决方案2】:

您认为使用画布在 Firefox 上截屏速度慢的假设是错误的。

我做了几张截图,Firefox/canvas 比 Chrome/captureVisibleTab 快。

实际上 Firefox 更适合尽可能快地截屏,因为它的画布向特权代码公开了 mozFetchAsStream 方法,从而可以绕过实际的瓶颈,即图像数据的 base64 编码。

一些数字

  • 铬:captureVisibleTab 200-205ms
  • 火狐:drawImage 20-25ms + toDataURL 125-130ms

devtools screenshot 命令是a good example 如何只捕获可见部分

平心而论,为了进行有意义的比较,必须考虑 Chrome 的 PNG 编码器是否更倾向于压缩而不是速度。尽管如此,这并没有改变 Firefox 的画布很好的事实。

edit: 好的,那 base64 encoding 这句话是愚蠢的,我不知道我在想什么。也许我应该写的是 Firefox 的画布不仅速度快而且用途广泛。

【讨论】:

  • 精湛的测试人@我喜欢这样的测试!还了解了一些关于mozFetchAsStream 的好处。不知道 base64 是瓶颈。
  • @Noitidart 不是,我的意思是在 Firefox 上,如果有必要,您可以避免将 b64 编码数据转换回二进制。
  • 示例链接已损坏
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 2020-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多