咱们在前端报表中实现了各种工作数据的输出或内容解决之后,须要做什么?
数据的导出!
这些数据的罕用导出格局有:PDF、Excel、HTML和图片几大类型。
但总有一些理论利用场景,须要的不仅仅是将现有内容导出,还须要咱们对一些内容的格局进行转化。
就在前几天,葡萄刚下班,就看到客户发来下图,产生了以下对话
-葡萄,这一页能够导出吗?
-当然能够,PDF、Excel、HTML都能够。
-可是我想把这一页导出图片。
这时候问题就呈现了,在咱们的前端电子报表中并没有默认图片保留的格局,那这时候咱们如何用已有性能进一步扩大,来实现这个性能呢?
一、确定实现思路
巧妇难为无米之炊,首先咱们先整顿一下手中素材。
通过浏览文档理解咱们能够自定义增加按钮:
同时咱们还能够在action属性中,给按钮定义点击后触发的事件:
顺着这个思路,咱们能够在工具栏增加一个导出按钮,将按钮的动作设置为"点击这个按钮时实现导出图片的性能"。ARJS自身反对导出PDF,并且也提供了间接调用导出PDF的接口:export,所以咱们能够先通过接口导出PDF,而后再将PDF转换为图片,最终实现导出图片的性能。
这下子,咱们的最终问题就变成了是如何 将 PDF 转换为图片并导出 。
PDF.js是一款应用HTML5 Canvas平安地渲染PDF文件以及听从网页规范的网页浏览器渲染PDF文件的JavaScript库。咱们能够通过PDF.js库将导出的PDF通过Canvas在网页上渲染进去,而后通过Canvas的toDataURL办法返回一个蕴含图片展现的 data URL。拿到这个URL就好办了,能够利用a标签的download属性间接对其进行下载,最终实现在ARJS中导出图片的性能。
总结,整体实现思路如下:
- 增加导出图片按钮
- 实现导出PDF
- 将 PDF 通过 PDF.js 库渲染成 <canvas>
- 通过a标签的download属性将<canvas>保留为图片
二、代码实战
简略起见,本示例不应用任何框架集成ARJS,抉择在纯JaveScript中集成报表,大家能够浏览相干文档:在纯JavaScript我的项目中集成报表 Viewer。另外,为了在document中插入canvas元素,当时能够建设一个div元素,以便之后在该节点下插入canvas元素;同时为了界面中只有报表查看器,能够暗藏该div。最终的页面构造如下:
<body> <div id="viewer-host"></div> <div id="imgDiv" style="display: none"></div> </body>
增加导出图片按钮
1. let exportImageButton = {2. key: '$exportImage',3. icon:{4. type: 'svg',5. content:'<svg role="img" xmlns="http://www.w3.org/2000/svg" width="21px" height="21px" viewBox="0 0 24 24" aria-labelledby="imageIconTitle" stroke="#205F78" stroke-width="2.2857142857142856" stroke-linecap="square" stroke-linejoin="miter" fill="none" color="#205F78"> <title id="imageIconTitle">Image</title> <rect width="18" height="18" x="3" y="3"/> <path stroke-linecap="round" d="M3 14l4-4 11 11"/> <circle cx="13.5" cy="7.5" r="2.5"/> <path stroke-linecap="round" d="M13.5 16.5L21 9"/> </svg>',6. size: 'small'7. },8. enabled: true,9. title:'导出图片',10. action: function() {11. //定义导出图片按钮点击事件12. }13. };14. viewer.toolbar.addItem(exportImageButton);
接口文档:addItem。
(提醒:以上在icon 的content的属性中,应用了一个svg,这个示例代码中的svg来自网站:ikonate 。如果大家有须要可自行下载,如果作为商用须要留神版权 )
以上代码增加之后,咱们就能够在报表预览界面的工具栏看到这样一个按钮:
实现导出PDF
在exportImageButton的action中定义一个exportImage办法,在这个办法中首先实现导出PDF,导出的后果蕴含一个PDF文件的blob对象,大家可自行打印进去看一下导出后果:
function exportImage() { const settings = { title: 'Active Reports JS' }; viewer.export('PDF', settings).then((result) =>{ //这个result蕴含一个所导出PDF的blob对象 console.log(result); }); }
将PDF通过PDF.js库渲染成canvas
首先咱们须要去PDF.js官网下载相干文件引入到我的项目中,我这里的示例通过cdn的形式引入:
1. <script src="https://cdnjs.cloudflare.com/ajax/libs/PDF.js/2.10.377/PDF.min.js"></script>
引入之后,咱们就能够对上一步失去的blob对象进行操作,将PDF渲染成\<canvas\>:
function pageToCanvasObj(page) { const viewport = page.getViewport({scale: 1}); const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; canvas.style.width = "100%"; canvas.style.height = "100%"; imgDiv.append(canvas); return { canvas, renderContext: { canvasContext: context, viewport } } } function exportImage() { const settings = { title: 'Active Reports JS' }; viewer.export('PDF', settings).then((result) =>{ //外围代码 //通过FileReader的接口将blob转换为ArrayBuffer const fileReader = new FileReader(); fileReader.readAsArrayBuffer(result.data); fileReader.onload = function() { //为了读写ArrayBuffer对象,建设typedArray视图 const typedArrayResult = new Uint8Array(fileReader.result); //PDF.js读取文档后渲染canvas PDFjsLib.getDocument(typedArrayResult).promise.then(function(PDF) { if (PDF) { const pageNum = PDF.numPages; for (let i = 1; i <= pageNum; i++) { PDF.getPage(i).then((page) => { //创立canvas,并且返回相干数据 const canvasObj = pageToCanvasObj(page); //<canvas>渲染 page.render(canvasObj.renderContext).promise.then(() => { //通过canvas对象的toDataURL失去图片链接 const imgUrl = canvasObj.canvas.toDataURL(); }) }) } } },(error) => { alert(error); }); }; }); }
通过a标签的download属性将canvas保留为图片
将上一步失去的imgURL通过a标签下载:
function saveImage(index, url) { const link = document.createElement("a"); link.href = url; link.download = `image${index}`; link.click(); link.remove(); }
这下就实现了在在前端报表中残缺将报表内容作为图片导出。在此附上示例残缺demo代码文件:
https://gcdn.grapecity.com.cn...;aid=MTY0Njg4fGNlMzM5MTkwfDE2MzM2NjU4MzB8NjI2NzZ8MTMyNDM3
导出成果:
到这里,曾经齐全解决了本次提到的问题~
后续也会为大家带来更多乏味或庄重的内容。