找回密码
 立即注册

QQ登录

只需一步,快速开始

Crystal.Li 讲师达人认证 悬赏达人认证
论坛元老   /  发表于:2021-9-30 15:25  /   查看:3316  /  回复:1
本帖最后由 Crystal.Li 于 2021-9-30 15:30 编辑

众所周知,目前Active Reports JS可支持导出的文件类型有Pdf、Excel、Html三大类型。但是,总有一些实际应用场景,需要我们导出图片,那这时候我们该如何满足呢?

产品是标准的,但办法是灵活的。虽然标准产品目前没有直接支持导出图片,但却暴露了很多可供用户进行定制化产品的接口,所以本文就从产品所提供的接口入手,探索一下如何在标准产品中实现导出图片的功能,同时在文末会附上可直接运行的demo文件。

一、确定实现思路

在文档中,我们知道ARJS支持自定义添加按钮:

从在线示例里边,我们知道在action属性中可以给按钮定义点击后触发的事件:

所以我们可以在工具栏添加一个导出图片按钮,当点击这个按钮时实现导出图片的功能。我们知道,ARJS本身支持导出pdf,并且也提供了直接调用导出pdf的接口:export,所以我们可以先通过接口导出pdf,然后再将pdf转换为图片,最终实现导出图片的功能。

经过以上分析,我们的最终问题其实就是如何将pdf转换为图片并导出PDF.js是一款使用HTML5 Canvas安全地渲染PDF文件以及遵从网页标准的网页浏览器渲染PDF文件的JavaScript库。我们可以通过PDF.js库将导出的pdf通过Canvas在网页上渲染出来,然后通过Canvas的toDataURL方法返回一个包含图片展示的 data URI。拿到这个URI就好办了,可以利用a标签的download属性直接对其进行下载,最终实现在ARJS中导出图片的功能。

总结,整体实现思路如下:
  • 添加导出图片按钮
  • 实现导出 pdf
  • 将 pdf 通过 pdf.js 库渲染成 <canvas>
  • 通过a标签的 download 属性将 <canvas> 保存为图片


二、代码实战
简单起见,本示例不使用任何框架集成ActiveReports JS,在纯JaveScript中集成报表,相关文档:在纯JavaScript项目中集成报表 Viewer。另外,为了在document中插入canvas元素,事先可以建立一个div元素,以供之后在该节点下插入canvas元素,同时为了界面中只有报表查看器,可以隐藏该div。最终的页面结构如下:
  1. <body>
  2.         <div id="viewer-host"></div>
  3.         <div id="imgDiv" style="display: none"></div>
  4. </body>
复制代码

1、添加导出图片按钮
  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 如果大家有需要可自行下载,如果作为商用需要注意版权~)

以上代码添加之后,我们就可以在报表预览界面的工具栏看到这样一个按钮:


2、实现导出 pdf
在exportImageButton的action中定义一个exportImage方法,在这个方法中首先实现导出pdf,导出的结果包含一个pdf文件的blob对象,大家可自行打印出来看一下导出结果:
  1.     function exportImage() {
  2.         const settings = { title: 'Active Reports JS' };
  3.         viewer.export('pdf', settings).then((result) =>{
  4.                 //这个result包含一个所导出pdf的blob对象
  5.                 console.log(result);
  6.         });
  7.     }
复制代码

3、将 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>:
  1.     function pageToCanvasObj(page) {
  2.         const viewport = page.getViewport({scale: 1});
  3.         const canvas = document.createElement('canvas');
  4.         const context = canvas.getContext('2d');
  5.         canvas.height = viewport.height;
  6.         canvas.width = viewport.width;
  7.         canvas.style.width = "100%";
  8.         canvas.style.height = "100%";
  9.         imgDiv.append(canvas);
  10.         return {
  11.             canvas,
  12.             renderContext: {
  13.                 canvasContext: context,
  14.                 viewport
  15.             }
  16.         }
  17.     }

  18.     function exportImage() {
  19.         const settings = { title: 'Active Reports JS' };
  20.         viewer.export('pdf', settings).then((result) =>{
  21.             //核心代码
  22.            //通过FileReader的接口将blob转换为ArrayBuffer
  23.             const fileReader = new FileReader();
  24.             fileReader.readAsArrayBuffer(result.data);
  25.             fileReader.onload = function() {
  26.                 //为了读写ArrayBuffer对象,建立typedArray视图
  27.                 const typedArrayResult = new Uint8Array(fileReader.result);
  28.                 //pdf.js读取文档后渲染canvas
  29.                 pdfjsLib.getDocument(typedArrayResult).promise.then(function(pdf) {
  30.                     if (pdf) {
  31.                         const pageNum = pdf.numPages;
  32.                         for (let i = 1; i <= pageNum; i++) {
  33.                             pdf.getPage(i).then((page) => {
  34.                                 //创建canvas,并且返回相关数据
  35.                                 const canvasObj = pageToCanvasObj(page);
  36.                                 //<canvas>渲染
  37.                                 page.render(canvasObj.renderContext).promise.then(() => {
  38.                                    //通过canvas对象的toDataURL得到图片链接
  39.                                     const imgUrl = canvasObj.canvas.toDataURL();
  40.                                 })
  41.                             })
  42.                         }
  43.                     }
  44.                 },(error) => {
  45.                     alert(error);
  46.                 });
  47.             };
  48.         });
  49.     }
复制代码

4、通过a标签的 download 属性将 <canvas> 保存为图片

将上一步得到的imgUrl通过a标签下载:
  1.     function saveImage(index, url) {
  2.         const link = document.createElement("a");
  3.         link.href = url;
  4.         link.download = `image${index}`;
  5.         link.click();
  6.         link.remove();
  7.     }
复制代码

以上就实现了在ActiveReports中导出图片的功能,其中无非是一些文件读写以及dom相关的操作。在此附上示例完整demo代码文件:

导出效果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

1 个回复

正序浏览
qq525566534
中级会员   /  发表于:2021-10-12 08:38:14
沙发
多谢,我实验下哈
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部