浅析浅析js实现网页截图的两种方式实现网页截图的两种方式
主要介绍了浅析js实现网页截图的两种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一
定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Web端的截图(生成图片)并不算是个高频的需求,资料自然也不算多,查来查去,也不过Canvas 和 SVG两种实现方案,原理
大概相似,都非真正义上的截图而是把DOM转为图片,然而实现方式却截然不同。
Canvas 实现实现
如何将dom转换成canvas图片?自然是要一点点画到canvas里,想想都是件麻烦事。通过分析github的知名截图库
niklasvh/html2canvas (7k+ star)的源码,梳理了其大致的思路:
递归取出目标模版的所有DOM节点,填充到一个rederList,并附加是否为顶层元素/包含内容的容器 等信息
通过z-index postion float等css属性和元素的层级信息将rederList排序,计算出一个canvas的renderQueue
遍历renderQueue,将css样式转为setFillStyle可识别的参数,依据nodeType调用相对应canvas方法,如文本则调用
fillText,图片drawImage,设置背景色的div调用fillRect等
将画好的canvas填充进页面
无论是排序优先级的计算还是从css到canvas的转换,毫无疑问都是些巨麻烦的事,尤其是放在真实的业务场景里,DOM模版
中往往会包含复杂的样式与排版,html2canvas 足足用了20多个js来实现这层转换,复杂成度可见一斑。索性,我们不需要再
重新造一遍轮子。
使用canvas转化的话灵活性较高,环境依赖上也只需要确保浏览器支持canvas就可以了,但它有个显著的缺点:慢。原因自
然是因为大量的计算与递归调用,这是无可避免的。不过html2canvas代码中大量使用了Promise,所以html2canvas 支持异
步操作。
限制:
无法跨域跨域资源
无法渲染iframe,flash等内容,但目前支持svg
值得一提的是,尽管html2canvas主页表示它还处于实验室环境,但自14年起便已经被Twitter 等用在了生产环境,所以虽然有
诸多限制,稳定性应该还是保障的。
canvas如此复杂,那么有没有一种更简单的方法呢?
自然是有的,那便是SVG
SVG实现实现
首先,svg本来就是矢量图形;其次,svg是可以用xml描述的;再其次,用来描述svg的标签里有个 foreignObject标签,这个
标签可以加载其它命名空间的xml(xhtml)文档。也就是说,如果使用svg的话,我们不再需要一点点的遍历,转换节点;不用
再计算复杂的元素优先级,只需要一股脑的将要渲染的DOM扔进<foreignObject></foreignObject>就好了,剩下的就交给浏览
器去渲染。
让我们理一理思路:
首先,我们要声明一个基础的svg模版,这个模版需要一些基础的描述信息,最重要的,它要有<foreignObject>
</foreignObject>这对标签
将要渲染的DOM模版模版嵌入foreignObject
利用Blob构建svg图像
取出URL,赋值给
<div id='text'>
<h1 style="background-color: #ccc;width: 200px;height: 200px;" >Hello World</h1>
</div>
//此代码仅在chrome测试下通过
function html2Svg (domStr) {
//创建模版字符串
var svgXML=
`<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<foreignObject width="100%" height="100%">${generateXML(html)}</foreignObject>
</svg>`
//利用Blob创建svg
var svg = new Blob([svgXML], {type: 'image/svg+xml'})
//利用DOMURL.createObjectURL取出对象
var url = window.URL.createObjectURL(svg);
var img = new Image()
img.src = url
return img
}