这篇工作总结将整理一下如何实现html生成图片。
生成图片一般的思路都是将需要生成图片的dom绘制到canvas中,再调用canvas.toDataURL()
将绘制好的canvas转成file对象,然后再上传服务器,拿到线上地址,再显示出来。
最麻烦的就是将dom绘制到canvas,摘自网上的说法,需要先遍历需要生成图片区域的所有元素,提取DOM数,然后获取渲染之后的每个DOM节点的内联、外链CSS属性,最后将样式转换成canvas的属性,利用offset等属性辅助摆放位置,将节点对应到canvas上。所以更多人实现的方案是使用第三方库html2canvas
。
html2canvas
用法也很简单,就是一个html2canvas()
方法,传入需要生成图片的dom跟配置,然后这个方法支持Promise,可以使用html2canvas(dom).then
方法写入一个回调函数,拿到绘制完成的canvas
,就可以完成接下来的处理了。
这里整理一下开发中遇到的需求跟处理。一般生成的图片会跟页面显示不同,因为可能会加一些内容。这样就需要在调用html2canvas()
方法先调整需要生成图片的dom的样式,改成需要的样式效果。然后在回调函数中,等拿到canvas
之后,再把dom的样式恢复。
1 | // 使用vue开发 |
关于图片模糊的问题
上面的操作可以拿到canvas,然后就可以转file对象,上传,拿到服务端链接,然后打开一看,图片很模糊。
这个问题也很常见,一方面跟设备的dpi有关,另一方面跟生成的图片太小,拉伸之后也会出现这个问题。所以解决的方案是在调用html2canvas()
方法先把需要生成图片的dom的整体样式放大数倍,然后再生成图片,同时在调用方法时设置dpi
跟scale
两个配置,这样能保证图片效果。
1 | htmlToImage () { |
关于跨域图片不显示的问题
所以又按照上面的思路改了一下,图片是终于清晰了,但是还有一个问题没解决,就是本来应该显示的图片没有出现。这个问题我搜索过之后才知道原来是图片跨域的问题。
一般图片跨域没什么问题,但是在canvas上,跨域图片会导致画布被污染,所以跨域图片不会被绘制到canvas上,最终生成的图片也没有正常显示该图片。
解决这个问题,我试过一些网上的简单的处理,都无效,所以只能把跨域图片转为本地图片,再设置html2canvas()
的useCORS
为true
。
跨域图片转为本地图片,目前我的解决方案是让服务器返回二进制数据,然后转成Blob对象,再调用window下的createObjectURL()
方法转成本地图片url。
关于base64转Blob对象转file对象
这个问题打算单独整理,就不再这里写了。