乐趣区

关于javascript:在纯JaveScript中实现报表导出从PDF到JPG

咱们在前端报表中实现了各种工作数据的输出或内容解决之后,须要做什么?

数据的导出!

这些数据的罕用导出格局有: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 渲染成 \&lt;canvas\&gt;:

        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
导出成果:

到这里,曾经齐全解决了本次提到的问题~

后续也会为大家带来更多乏味或庄重的内容。

退出移动版