在纯JaveScript中实现报表导出(从“PDF”到“JPG”)

我们在前端报表中完成了各种工作数据的输入或内容处理之后,需要做什么?
数据的导出!
这些数据的常用导出格式有:PDF、Excel、HTML和图片几大类型。
但总有一些实际应用场景,需要的不仅仅是将现有内容导出,还需要我们对一些内容的格式进行转化。
就在前几天,葡萄刚上班,就看到客户发来下图,发生了以下对话
-葡萄,这一页可以导出吗?
-当然可以,PDF、Excel、HTML都可以。
-可是我想把这一页导出图片。
在纯JaveScript中实现报表导出(从“PDF”到“JPG”)
文章图片

这时候问题就出现了,在我们的前端电子报表中并没有默认图片保存的格式,那这时候我们如何用已有功能进一步扩展,来实现这个功能呢?
在纯JaveScript中实现报表导出(从“PDF”到“JPG”)
文章图片

一、确定实现思路
巧妇难为无米之炊,首先我们先整理一下手中素材。
【在纯JaveScript中实现报表导出(从“PDF”到“JPG”)】通过阅读文档了解我们可以自定义添加按钮:
在纯JaveScript中实现报表导出(从“PDF”到“JPG”)
文章图片

同时我们还可以在action属性中,给按钮定义点击后触发的事件:
在纯JaveScript中实现报表导出(从“PDF”到“JPG”)
文章图片

顺着这个思路,我们可以在工具栏添加一个导出按钮,将按钮的动作设置为"点击这个按钮时实现导出图片的功能"。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 库渲染成
  • 通过a标签的download属性将保存为图片
二、代码实战
简单起见,本示例不使用任何框架集成ARJS,选择在纯JaveScript中集成报表,大家可以阅读相关文档:在纯JavaScript项目中集成报表 Viewer。另外,为了在document中插入canvas元素,事先可以建立一个div元素,以便之后在该节点下插入canvas元素;同时为了界面中只有报表查看器,可以隐藏该div。最终的页面结构如下:

添加导出图片按钮
1.let exportImageButton = { 2.key: '$exportImage', 3.icon:{ 4.type: 'svg', 5.content:' Image - 锐客网 ', 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 。如果大家有需要可自行下载,如果作为商用需要注意版权 )
以上代码添加之后,我们就可以在报表预览界面的工具栏看到这样一个按钮:
在纯JaveScript中实现报表导出(从“PDF”到“JPG”)
文章图片

实现导出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.

引入之后,我们就可以对上一步得到的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); //渲染 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 = https://www.it610.com/article/url; link.download = `image${index}`; link.click(); link.remove(); }

这下就实现了在在前端报表中完整将报表内容作为图片导出。在此附上示例完整demo代码文件:
https://gcdn.grapecity.com.cn...; aid=MTY0Njg4fGNlMzM5MTkwfDE2MzM2NjU4MzB8NjI2NzZ8MTMyNDM3
导出效果:
在纯JaveScript中实现报表导出(从“PDF”到“JPG”)
文章图片

到这里,已经完全解决了本次提到的问题~
后续也会为大家带来更多有趣或严肃的内容。
在纯JaveScript中实现报表导出(从“PDF”到“JPG”)
文章图片

    推荐阅读