屏幕截图是 JavaScript 运用中非常有代价且主要的一部分。
像 Google 这样的公司利用它们来从用户那里得到反馈,Bugherd 类似的产品将屏幕截图用作其产品的核心部分,并且非常适宜数据导出(例如图表)。

如果哀求用户对他们所看的内容进行屏幕截图,会给用户带来很多麻烦。
首先,他们须要知道键盘快捷键( MacOS 和 Windows 是不同的)。

然后他们须要知道接下来该怎么做。
例如,他们可以将其上传到诸如 Dropbox 之类的某个地方或将其通过邮件发送给您。
大多数用户可能也不知道如何调度或优化屏幕截图的质量。
如果您自己存储屏幕截图,则要确保它们占用尽可能少的空间,从而确保您的花费尽可能少。

jsp服务器屏幕截图在阅读器中若何应用JavaScript截图 Docker

接下来,先容三种自动为用户捕获屏幕截图的方法。

1、利用html2canvas进行客户端屏幕截图

2011年 Niklas von Hertzen 在Stackoverflow回答了一个问题,称可以将页面的DOM放入HTML Canvas中,并利用它来天生屏幕截图。
随后他公开了代码,并更新了答案,即HTML2Canvas。
后来的调查显示,Google利用一种非常相似的技能来自动天生屏幕截图,去供应用户反馈,来作为证据,并且对大型产品也足够健壮。

如何利用html2canvas

这个非常大略,当你要天生屏幕截图时,你只须要获取DOM(页面的HTML),然后将DOM通报到HTML Canvas中。
在某些限定下,canvas元素可以天生一个data URI(作为base64字符串)。
下面的示例天生屏幕截图,并将其作为图像在窗口中打开。

const screenshotTarget = document.body;html2canvas(screenshotTarget).then((canvas) => { const base64image = canvas.toDataURL("image/png"); window.location.href = base64image;});利用canvas的优缺陷优点

快。
你不须要等待任何外部做事,这统统都是在客户端上完成的。
虽然 html2canvas 并未每天更新,但常日每隔几个月,都会定期看到它的更新和修复。
社区很强大且生动,在那里超过40个 pull request 是开放的,并记录了600多个问题(截至2020年7月)。
在 Stack Overflow 也有很多的问题(和答案!
)。
良好的浏览器兼容性,html2canvas 已有9年的历史,并且仍旧保持出色的浏览器兼容性。

缺陷

不支持Shadow DOM(或Web Component)。
这里有一个开放的 pull request 去增加了支持,掩护者看起来非常渴望去合并这个分支。

跨域限定。
当你往Canvas中增加包含要求的元素,比如图片或者css样式等,他们会由于跨域策略而被谢绝。

并不是所有的CSS属性都能支持。
文档中明确提到了 “html2canvas 将不会供应完全的CSS能力” 。

2. 利用 getDisplayMedia 天生截图

在 html2canvas 发布的同一韶光,关于Web该当支持原生视频通话的想法也得到了众人的追捧。
在 2011 年,Google 发布了 Hangouts,一个实时视频和音频平台。
为了支持 Hangouts,Google 提出并实现了实时通讯(RTC)的想法,RTC 随后也发展为了 WebRTC。
WebRTC 已经变为了所有当代浏览器的标准,它是 Web 实时视频、音频和数据传输的根本举动步伐。

getDisplayMedia 是 WebRTC 中用来做屏幕分享的一个API。
你可以从视频中截取一个静态图像,就像屏幕分享一样,但本色上是屏幕截图。
来让我们看一个基本的例子:

const capture = async () => { const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); const video = document.createElement("video"); try { const captureStream = await navigator.mediaDevices.getDisplayMedia(); video.srcObject = captureStream; context.drawImage(video, 0, 0, window.width, window.height); const frame = canvas.toDataURL("image/png"); captureStream.getTracks().forEach(track => track.stop()); window.location.href = frame; } catch (err) { console.error("Error: " + err); }};capture();

虽然以上的例子没有第一个例子那么简洁,它依然很随意马虎理解。
首先,在内存中创建了canvas和video元素,然后 getDisplayMedia API用来要求访问用户的桌面或选项卡。
在用户授权之后,屏幕流被设置到video元素,然后绘制到canvas上。
从canvas中导出图片,可以利用和html2canvas示例中相同的方法。

getDisplayMedia API的优缺陷优点

良好的当代浏览器支持 - 是原生API,也便是内建在浏览器中,意味着它不须要依赖任何第三方的脚本和代码。

可扩展性 - 正如你所看到的,利用相同的API,在未来你可以很随意马虎的增加视频录制的功能。

桌面 || 标签页 - getDisplayMedia API 可以录制其他的桌面或浏览器的窗口,这使它变得强大,可以给你的运用之外的东西截图。

缺陷

权限 - 你须要获取用户的权限。
由于依赖于浏览器,权限对话框可能看起来不一样,有时候让人有点困扰。

慢 - 由于你须要获取权限,这须要花费用户一些韶光去点击和理解发生了什么。
如果用户须要急速获取截图,这个小UI交互对付截取韶光敏感的内容,会有一些延迟。

3. 截图做事

截图做事正在变得盛行,它供应了一个随意马虎的办法将截图功能集成到你的运用中。
然而它不在客户端实行,须要利用类似 url2png、Stillio、Urlbox的做事,这也意味着你不用关系利用什么根本举动步伐来获取截图。

只管每个做事可能实现的办法不同,但思路大致相同。
你发送一个URL(同时自定义参数:尺寸、格式、质量)到外部做事,然后等待返回相应数据。
这些常日利用后端做事处理,让我们来看一下利用url2png和Nodejs、Express的实现。

const url2png = require('url2png')('API_KEY', 'PRIVATE_KEY');const fs = require('fs');app.get('/screenshot', (req, res) => {url2png.readURL(req.query.url, {}).pipe(fs.createWriteStream('screenshot.png'));res.json({success: true})});

以上的例子,我们可以利用下面这种形式来要求:

/screenshot?url=http://google.com.au

实际上,我们是利用url2png库来天生一个截图。
截图会被保存在本地文件系统,或者你可以通过接口返回。

截图做事的优缺陷优点

后处理 - 可以供应更多后处理的功能,比如灵巧的设置图片格式,尺寸,质量,等等;

健壮性 - 可以供应给很多用户利用,随意马虎处理大量的要求。
你不须要去掩护截图过程干系的根本举动步伐,如果你高兴,像 PhantomJS项目 和 SauceLabs 做事,都是一个好的开始。

缺陷

无状态 - 截图可能不是用户看到的那样子,例如,如果用户已经在页面中做过了一些交互,或者页面须要登录,截图做事可能无法截图相同的页面。

本钱 - 以上三个选择中,这是唯一一个须要本钱的。
虽然它相称便宜,如果你要处理大量的截图需求,它就会比较昂贵。

韶光 - 截图做事可能会花费几分钟去天生和返回一张图片。

综上所述

如果你正在将截图作为一个主要的功能集成到你的运用中,你须要好好衡量一下每个方案的优缺陷。

利用客户端方案,例如html2canvas 或 getDisplayMedia API,意味着你不须要管理任何做事端举动步伐,而且能够快速的天生截图。

如果你须要像素级的还原用户看到的画面,同时对付偶尔涌现的授权弹框不介意,那么 getDisplayMedia API 将是好的开始。

如果你希望快速获取一个不太精确的截图,同时没有额外的做事依赖,html2canvas 可能是一个更好的选择。