屏幕截图是 JavaScript 运用中非常有代价且主要的一部分。像 Google 这样的公司利用它们来从用户那里得到反馈,Bugherd 类似的产品将屏幕截图用作其产品的核心部分,并且非常适宜数据导出(例如图表)。
如果哀求用户对他们所看的内容进行屏幕截图,会给用户带来很多麻烦。首先,他们须要知道键盘快捷键( MacOS 和 Windows 是不同的)。
然后他们须要知道接下来该怎么做。例如,他们可以将其上传到诸如 Dropbox 之类的某个地方或将其通过邮件发送给您。大多数用户可能也不知道如何调度或优化屏幕截图的质量。如果您自己存储屏幕截图,则要确保它们占用尽可能少的空间,从而确保您的花费尽可能少。
接下来,先容三种自动为用户捕获屏幕截图的方法。
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 可能是一个更好的选择。