html2canvas+jspdf实现html网页转pdf,并解决图片跨域及分页问题
项目中需要将html页面转化为pdf保存下来,于是开始尝试网页转图片再转pdf的方案(即html2canvas+jspdf),经历了一番折腾,最终终于实现了html转pdf,虽然因为一些问题最终没有选择这种方案,但还是决定先记录下来...
直接上干货--源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.4/jspdf.debug.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span> <span class="hljs-tag"><<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"~/Content/js/healthyCabin/monitorData/html2canvas.js"</span>></span><span class="hljs-tag"></<span class="hljs-name">script</span>></span> <span class="hljs-tag"><<span class="hljs-name">script</span>></span><span class="javascript"> <span class="hljs-keyword">var</span> downPdf = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"exportToPdf"</span>); downPdf.onclick = <span class="hljs-function"><span class="hljs-keyword">function</span> () </span>{ <span class="hljs-comment">// 要导出pdf的节点</span> <span class="hljs-keyword">var</span> elements = <span class="hljs-built_in">document</span>.getElementsByClassName(<span class="hljs-string">"pdf_page"</span>); <span class="hljs-keyword">var</span> imgMap = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>(); <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> index = <span class="hljs-number">0</span>; index < elements.length; index++) { <span class="hljs-keyword">var</span> mapIndex = index; html2canvas(elements[index], { allowTaint: true, // 支持跨域 <span class="hljs-attr">useCORS</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">// 是否允许网页中img元素跨域,这个设置需要img元素支持及服务器支持</span> scale: <span class="hljs-number">2</span>, <span class="hljs-comment">// 这个影响生成图片的清晰度</span> background: <span class="hljs-string">"#F5F5F5"</span> <span class="hljs-comment">//背景</span> }).then(<span class="hljs-function">(<span class="hljs-params">canvas</span>) =></span> { <span class="hljs-keyword">var</span> img = <span class="hljs-keyword">new</span> Image(); img.width = canvas.width; img.height = canvas.height; img.src = canvas.toDataURL(<span class="hljs-string">'image/jpeg'</span>, <span class="hljs-number">1.0</span>); imgMap.set(mapIndex, img); <span class="hljs-comment">// 按照顺序保存图片</span> <span class="hljs-keyword">if</span>(imgMap.size == elements.length) { <span class="hljs-comment">// 当所有图片都转化完毕,则进行保存操作</span> <span class="hljs-keyword">var</span> pdf = <span class="hljs-keyword">new</span> jsPDF(<span class="hljs-string">''</span>, <span class="hljs-string">'pt'</span>, <span class="hljs-string">'a4'</span>); <span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < imgMap.size; i++) { <span class="hljs-comment">// canvas尺寸</span> <span class="hljs-keyword">var</span> canvasWidth = imgMap.get(i).width; <span class="hljs-keyword">var</span> canvasHeight = imgMap.get(i).height; <span class="hljs-keyword">var</span> pageData = imgMap.get(i).src; addOneImg(pdf, pageData, canvasWidth, canvasHeight); <span class="hljs-keyword">if</span>(i < imgMap.size<span class="hljs-number">-1</span>) { pdf.addPage(); <span class="hljs-comment">// 如果还有图片未添加到pdf,则增加一个页面</span> } } <span class="hljs-comment">// 所有图片添加完毕,保存</span> pdf.save(<span class="hljs-string">"report_"</span>+checkId+<span class="hljs-string">".pdf"</span>); } }); }; } <span class="hljs-comment">// img转化为pdf并保存</span> <span class="hljs-keyword">var</span> addOneImg = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">pdf, pageData, canvasWidth, canvasHeight</span>) </span>{ <span class="hljs-comment">// a4纸的尺寸[595.28,841.89]</span> <span class="hljs-keyword">var</span> a4Width = <span class="hljs-number">595.28</span>; <span class="hljs-keyword">var</span> a4Height = <span class="hljs-number">841.89</span>; <span class="hljs-comment">//html页面生成的canvas在pdf中图片的宽高</span> <span class="hljs-keyword">var</span> imgWidth = a4Width; <span class="hljs-keyword">var</span> imgHeight = a4Width / canvasWidth * canvasHeight; <span class="hljs-comment">//一页pdf显示html页面生成的canvas高度;</span> <span class="hljs-keyword">var</span> pageHeight = canvasWidth / a4Width * a4Height; addPages(pdf, pageData, <span class="hljs-number">0</span>, imgWidth, imgHeight, canvasHeight, pageHeight, a4Height); } <span class="hljs-comment">// 递归的方式对页面进行截取并添加到pdf中</span> <span class="hljs-keyword">var</span> addPages = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">pdf, pageData, position, imgWidth, imgHeight, canvasHeight, pageHeight, a4Height</span>) </span>{ pdf.addImage(pageData, <span class="hljs-string">'JPEG'</span>, <span class="hljs-number">0</span>, position, imgWidth, imgHeight) <span class="hljs-comment">// 减去已经绘制的区域</span> canvasHeight -= pageHeight; position -= a4Height; <span class="hljs-comment">// 当还有内容未生成pdf,则新加页面,并添加图片</span> <span class="hljs-keyword">if</span> (canvasHeight > <span class="hljs-number">0</span>) { pdf.addPage(); addPages(pdf, pageData, position, imgWidth, imgHeight, canvasHeight, pageHeight, a4Height); } } </span><span class="hljs-tag"></<span class="hljs-name">script</span>></span> |
需要注意的有以下几点:
- 这段代码是以a4纸的标准转换pdf,而且能够通过配置分页节点,达到分页可控的效果。
- 跨域方法:一. useCORS:true,并在后台header中添加Access-Control-Allow-Origin: * 二. 使用allowTaint: true, 然后如下图修改
html2canvas.js
如图,修改img.crossOrigin = 'anonymous'为img.crossOrigin = '',并修改img.src = src为img.src = src + (src.contain("?") ? "&" : "?") + "h2c_t" + new Date().getTime(),或者也可以直接下载下方提供的js:
js下载(点击下面文本链接进行下载):
原文博客:IT老五(html2canvas+jspdf实现html网页转pdf,并解决图片跨域及分页问题)

IT老五(it-lao5):关注公众号,一起源创,一起学习!