浏览器截屏思路
缘起
小伙伴来咨询浏览器如何截屏,脑子里正好有两个思路,跟小伙伴说了一下。趁现在脑子里还有印象,赶紧记录下来。 以前好像也遇到过这个需求,当时回复的是“浏览器没有这种能力”,现在回想起来,是当时自己的技术不过关,储备有限,思路过于狭隘导致的。。
声明
未编码实现,仅供参考。欢迎补充代码示例。
分析
浏览器截屏本质上只需要把当前浏览器视口中的视图生成图片即可,或者在浏览器中处理这个工作,或者在服务器端处理这个工作。
浏览器端实现方案
浏览器端可以生成图片的方案,最直接的方案是Canvas。将浏览器中当前DOM的内容渲染到Canvas中即可(可以直接使用Flipboard的HTML-Canvas库(当时Flipboard用来解决浏览器渲染性能的库),再将Canvas对应的imageData传到服务器解析即可;也可以使用SVG,SVG本质上是XML,和HTML最接近,将DOM对应的HTML转化为SVG的语法,也就完成了需求(SVG也可以看成一种图片格式)。
服务器端实现方案
思路的来源是PhantomJS所提供的截屏功能。
前提
- 静态网页(下文中将这个静态网页对应的URL称为S-URL);
- 或者能有办法将当前用户显示的网页内容映射下来的URL(下文中将此URL称为D-URL)。
基本思路
将当前需要截屏页面的信息(S-URL或D-URL,浏览器视口的大小,页面当前的位置)提交到服务器端,服务器端运行的PhantomJS根据上述信息进行渲染后生成图片并保存。
浏览器端实现方案和服务器端实现方案对比
- 浏览器端方案消耗的是客户端的计算能力,如果需要上传服务器,则需要消耗上行带宽;
- 服务器端方案消耗的是服务器端的计算能力,如果需要上传服务器,则需要消耗的上行带宽极小;但如果需要在浏览器端显示或使用,则需要消耗一定的下行带宽。
经典评论
其实如果是纯前端实现也只能使用canvas了吧,继伟说的使用svg最后也得用canvas转成dataurl才有意义,不然无法在客户端显示也不能做类似区域截图的功能,之前在王集鹄的博客里看到过利用svg的foreignobject元素实现截屏的文章,不过基本上算是黑魔法了,效果比直接用canvas差很多而且浏览器适配性也不好。其实就算用canvas也远没有看上去那么美,html2canvas之类的库的原理其实就是把所有dom元素在canvas上画一遍,所以object,iframe的内容都画不出来,貌似跨域的image也画不出来,加上canvas不支持低端浏览器,纯前端的解决方案对一些简单项目还行,复杂的还是依赖服务端更靠谱些,说到服务端的截图,基本上所有主流的互联网编程语言都有个实现的库,java有selenium,php有imagegrabscreen,python有PIL,还有寇云说到的nodejs的phantomjs,实现上也都比纯前端方案成熟稳定,效率也高。当然也有问题,比如不好处理异步请求渲染的内容等等,所以如果想要达到比较好的效果,用继伟文章里最后说的前后端结合的方案靠谱,前端上传截屏位置大小信息和页面内容等信息,服务端截图,截图后再发回前端预览…之前看EtherDream的微博,分享过一个xss截屏…(;一_一)…貌似是纯前端方案,效果还不错,他说过要写篇分享的,但后来也没看到,所以也不知道怎么实现的…