里讲一种实现起来比较简单的html转pdf下载的实现。
html2canvas jspdf
通过html2canvas,我们可以将指定的一个dom元素,渲染到canvas中,然后从canva中获得该图片,并将图片通过jspdf来生成。
function createPdf (selector,pagesize,direction,title){
var key = pagesize +''+direction;
var settings = {
'00' : {
pdf : {orientation : 'portrait',format : 'a4',unit : 'px'},
width : 448,
height : 632.5
},
'01' : {
pdf : {orientation : 'landscape',format : 'a4',unit : 'px'},
width : 632.5,
height : 448
},
'10' : {
pdf : {orientation : 'portrait',format : 'a3',unit : 'px'},
width : 632.5,
height : 894.2
},
'11' : {
pdf : {orientation : 'landscape',format : 'a3',unit : 'px'},
width : 894.2,
height : 632.5
}
};
var set = settings[key];
var doc = new jsPDF(set.pdf);
var arr = [];//根据顺序保存
var $arr = $(selector);
function tempCreate(){
if($arr.length == 0){//没有啦
//执行生成
tempPdf();
}else{
var $dom = $arr.splice(0,1);
html2canvas($dom[0]).then(canvas => {
var dataurl = canvas.toDataURL('image/png');
arr.push(dataurl);
tempCreate();
});
}
}
function tempPdf(){
arr.forEach((item,i)=>{
if(i !== 0){
doc.addPage();
}
doc.addImage(item,'png',-1,-1,set.width,set.height);//根据不同的宽高写入
})
//根据当前的作业名称
doc.save(title+'.pdf');
}
tempCreate();
}
需要指定容器(依赖jquery),然后指定纸张A4或 A3,以及横纵向。
//调用
createPdf('.single-page',0,0,'test')
当然,如果是数据量很大的话,就不建议在前台生成了,最好还是放在后端去做。个人测试过,做A4的图片生成PDF,当数量大约在100左右的时候,浏览器就崩溃了,如果只是几页的数据的话,这个方式还是很方便的。
Ps:浏览器要是现代浏览器哈。
html2canvas : http://html2canvas.hertzen.com/ jspdf :https://github.com/MrRio/jsPDF
avaScript HTML 渲染器
该脚本允许你直接在用户浏览器上对网页或其中一部分进行“截屏”。截屏是基于DOM的,因此对于真实内容的表示可能不是100%准确的,因为它不是生成实际的截图,而是基于页面上可用的信息构建截图。
工作原理
本脚本通过读取DOM和应用于元素的不同样式,将当前页面渲染为一个canvas(画布)图像。
它不需要来自服务器的任何渲染,因为整个图像是在客户机的浏览器上创建的。但是,由于它过度依赖于浏览器,所以这个库不适合在nodejs中使用。它也不会神奇地绕过任何浏览器的内容策略限制,因此在渲染跨域内容时将需要一个代理(https://github.com/niklasvh/html2canvas/wiki/Proxies )j将内容获取到相同的域(http://en.wikipedia.org/wiki/Same_origin_policy )中。
该脚本目前仍然处于非常实验性的状态,所以我不建议在生产环境中使用它,也不建议使用它构建应用程序,因为我们仍然会对它做较大的更改。
浏览器兼容性
这个库在以下浏览器中应该会运行良好(带有Promise polyfill):
由于每个CSS属性都需要手动构建才能得到支持,因此还有许多属性尚未得到支持。
用法
本 html2canvas 库利用了Promise,并期望它们在全局上下文中可用。如果你希望支持目前还不支持本地Promise的旧浏览器(http://caniuse.com/#search=promise ),请在包含 html2canvas 库之前先包含一个polyfill,如es6-promise(https://github.com/jakearchibald/es6-promise )。
要使用html2canvas渲染一个element,只需调用:html2canvas(element[, options]);
该函数会返回一个包含<canvas>元素的Promise(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise )。只需使用then向该Promise添加一个promise执行处理器即可:
构建
你也可以在这里下载已构建好的版本。(https://github.com/niklasvh/html2canvas/releases )
克隆 git源:
安装依赖:
构建浏览器包:
示例
获取更多信息和示例,请访问主页(https://html2canvas.hertzen.com/ )或尝试test console(测试控制台 https://html2canvas.hertzen.com/tests/ )。
贡献
如果你想对本项目贡献代码,请将推送请求发送至开发版分支。在提交任何更改之前,请在所有支持的浏览器上试运行并测试这些更改。如果一些CSS属性不被支持或显示不完整,在提交任何代码之前,请对这些CSS属性创建合适的运行环境进行测试。
英文原文:https://github.com/niklasvh/html2canvas 译者:浣熊君( ・᷄৺・᷅ )
条APP上有个截图分享功能,就是把文章转成一张图片,然后分享到各渠道中去,如微信、QQ等,非常实用,因此,打算就这项功能自己封装为一个组件ImageGenerator,后期专门进行图片生成,html是其中的一个源。
头条截图分享的实际效果图
目前前端使用较多的html转图片的工具是Html2Canvas,考虑技术储备和问题讨论的充裕性,决定封装一下这个工具。步骤如下:
按照官方要求,做安装操作:
npm
npm install html2canvas
我当时下载的是1.4.1的版本。
这个工具有自身的一些限制,使用时要注意:
[1] 并非真正的截图软件,而是根据DOM绘制出来的,其绘制能力,完全依赖于工具对DOM和对应属性的支持和理解;
[2] 因为使用了Canvas支持,生成图片的区域不能再有Canvas应用,否则会干扰工具的生成,不能保证生成预期,因此,如果使用了Canvas图表的应用这个工具不推荐使用
这个很简单,这里就是封装一个组件,用于后期引入html之外的源生成图片,同时也做一下图片的统一显示,从而和系统整体的设计进行配合。大致的实现思路如下:
上图,我们引入了工具本身,并设置的结果的显示区。生成的结果将以节点的方式注入 #image-box 中。
上图,封装了一个方法,用途是利用Html2Canvas工具获得图片,这里我们引入了一个组件的数据imageData用以存储和干预生成结果。在这里,我把ImageGenerator封装为全局组件。
我们在文章的尾部加入一个share功能,点击弹出分享设置的弹窗,实际效果如下图所示:
以上技术实现比较简单,这里就不进行赘述了。上图中,我们设置了一个生成图像按钮,点击该按钮则可以触发我们组件中的对应操作。关键思路包括:
【1】这里设置了一个封装组件shareHandler,封装了前导模块和imageGenerator,这两个模块的显示通过一个开关进行控制,该开关则通过图像生成成功事件进行赋值,这样的话,我们可以实现图片生成后,不再显示前导模块,而是显示图片结果,即ImageGenerator。
【2】这里有一个比较关键的操作是shareHandler通过触发事件将转换器发射到文章转换现场,为什么用事件,还是那句话,事件对于解耦和消除组件依赖是最自然的实现。注意,这里我把imageGenerator通过引用的方式作为参数传出了,这样的好处是事件将转换器代入了转换现场,并可以携带回现场转换结果。
【3】在文章查看器,solutionViewer中,自然会订阅事件、事件处理和取消订阅。注意这里的事件处理,实际上是调用了转换器中我们封装的函数,参数则是现场取得的,这里的机制很简单,定义要转换div的id,作为参数传入函数。
那么,点击图像后,我们可以看到效果图:
点击右键另存图像,我们可以获得一张png格式的图片,至于后续对下载和到粘贴板的支持,大家可以自行研究和实现。
实现过程中有几个注意事项:
【1】Canvas返回时,其长宽都是按照实际大小生成的,而我们的例子中,则要根据右抽屉式的弹窗做width=100%,height=auto的处理,这个要如何实现,就是要通过我们在imageGenerator中引入的imageData。
【2】我们的文章显示中,引入了文件管理的微服务,因此,文章中图片的链接都是跨域的,所以,必须打开html2Canvas的跨域选项,在封装的组件里,我是通过一共一个defaultOptions来实现这一点的。
这个选项可以在转换场景提供,也可提供一系列的默认值,最常用的除跨域外,还有是否允许log输出等开关,大家感兴趣可以自行查阅html2Canvas的官网。
内容比较简单,大家如果有这个应用场景,可以参考实现一下,有问题欢迎大家随时交流。谢谢大家的支持。
*请认真填写需求信息,我们会在24小时内与您取得联系。