记一个用 antv/g6 图表导出 PDF 时的画质偏低解决方案

先吐槽,antv/g6 绝对是我用过的最难用的图表库!谁用谁知道!一大堆不明所以的 api,不是一般的难用!而且有问题问GPT也没用,GPT用的还是G6旧的版本!

 

说下场景:展示出公司 A 的上下游公司,公司 A 的上下游公司 B 又要展示它的上游或者下游公司 C,画出一个关系图,如:

 

 

然后导出的时候,要用到官方的一个api: 

toDataURL
const dataURL = await graph.toDataURL({
                encoderOptions: 1, // 图片质量, 仅对 image/jpeg 和 image/webp 有效,取值范围 0 ~ 1
                mode: 'viewport' // viewport: 导出视口内容 overall: 导出整个画布 });

 

获取到 dataURL 后,再用 jspdf 进行处理,生成 PDF,处理完之后发现,无论怎么调,画质都很模糊,特别是当渲染的内容过多的时候;后来发现是 mode 的问题, 把 mode 改为 overall 就可以了,会进行全幅导出;但是这时候你发现,导出 JPG 没问题, 导出 PDF 比例失真了,还需要重新计算实际渲染图片的比列和 PDF 的比值,还要区分宽度比高度大、小的情况。直接贴代码记录:

        async downloadPdf(graph) {
            // console.log("graph", graph);
            // 将DataURL转换为PDF并下载
            // await graph.zoomTo(1);
            const dataURL = await graph.toDataURL({
                encoderOptions: 1, // 图片质量, 仅对 image/jpeg 和 image/webp 有效,取值范围 0 ~ 1
                mode: 'overall' // viewport: 导出视口内容 overall: 导出整个画布
            });
            const pdfName = `${this.sourceData.enterpriseName}产业图谱`;

            // 解决PDF导出比例问题,获取实际渲染的图片的宽高度,而不是画布宽高
            const img = await this.getImageDimensionsFromDataURL(dataURL);
            console.log('img', img.width, img.height)

            // 将base64的数据URL转换为二进制字符串
            var binary = atob(dataURL.split(",")[1]);
            // 为二进制字符串分配一个ArrayBuffer
            var array = new Uint8Array(binary.length);
            for (var i = 0; i < binary.length; i++) {
                array[i] = binary.charCodeAt(i);
            }
            // 使用ArrayBuffer创建Blob对象
            // const blob = new Blob([array], { type: "image/jpeg" });
            // 将DataURL转换为Blob

            // 创建jsPDF实例
            const pdf = new jsPDF();

            // 计算img与pdf宽度的比例,计算出pdf高度
            console.log('pdf size', pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight())
            const pdfWidth = pdf.internal.pageSize.getWidth();
            const pdfHeight = pdf.internal.pageSize.getHeight();
            const height = img.height;
            const width = img.width;

            if (width > height) {
                // 宽度大于高度的情况
                {
                    const w = pdfWidth;
                    const h =
                        height * (pdfWidth / width);
                    // 默认不居中,需要计算居中时y坐标
                    // const y = Math.abs(pdfHeight - h) / 2;
                    // 将Blob添加到PDF
                    pdf.addImage(array, "JPEG", 0, 0, w, h, pdfName, 'MEDIUM');
                }
            } else {
                // 宽度小于高度的情况
                {
                    let x = 0;
                    let h = pdfHeight;
                    let w =
                        width * (pdfHeight / height);
                    // 默认不居中,需要计算居中时x坐标
                    x = Math.abs(pdfWidth - w) / 2;

                    if (w > pdfWidth) {
                        w = pdfWidth;
                        h = height * (pdfWidth / width);
                        x = 0;
                    }


                    // 将Blob添加到PDF
                    pdf.addImage(array, "JPEG", x, 0, w, h, pdfName, 'MEDIUM');
                }
            }
            // 保存生成的PDF
            pdf.save(pdfName + ".pdf");
        },
        getImageDimensionsFromDataURL(dataUrl) {
            return new Promise((resolve, reject) => {
                // 创建一个Blob对象
                const byteString = atob(dataUrl.split(',')[1]); // 移除dataURL的前缀并解码Base64字符串
                const ab = new ArrayBuffer(byteString.length);
                const ia = new Uint8Array(ab);
                for (let i = 0; i < byteString.length; i++) {
                    ia[i] = byteString.charCodeAt(i);
                }
                const blob = new Blob([ab], { type: 'octet/stream' });
                const img = new Image();
                img.onload = function () {
                    resolve({ width: img.width, height: img.height });
                };
                img.onerror = function () {
                    reject(new Error('Failed to load image'));
                };
                // 创建一个可访问的URL并设置给img的src属性
                const url = URL.createObjectURL(blob);
                img.src = url;
            });
        },

 

 

 

 

 

posted @ 2025-02-13 10:37  CloudBarryChen  阅读(212)  评论(0)    收藏  举报