如何为Balkan OrgChartJS自定义编辑表单添加PDF导出功能
自定义OrgChartJS编辑表单的PDF导出解决方案
问题说明
我使用Balkan的OrgChartJS制作了自定义编辑表单,但目前无法将该表单导出为PDF。默认编辑表单自带PDF导出选项,但不清楚如何为包含HTML、CSS和图片的自定义编辑表单添加该功能。
现有JS代码
var chart; fetch('url', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ rootId: rootNodeId }) }) .then(response => response.json()) .then(data => { var myNodes = data.d; console.log(myNodes); OrgChart.scroll.smooth = 8; OrgChart.scroll.speed = 12; OrgChart.templates.ana.field_0 = '<text class="field_0 style="font-size:20px !important; font-family=verdana, Arial !important;" fill="#ffffff" x="120" y="30" text-anchor="middle">{val}</text>'; OrgChart.templates.ana.field_1 = '<text class="field_1 style="font-size:14px;font-family=verdana, Arial !important;" fill="#ffffff" x="120" y="50" text-anchor="middle">{val}</text>'; OrgChart.templates.ana.field_2 = '<text class="field_2 style="font-size:14px;font-family=verdana, Arial !important;" fill="#ffffff" x="150" y="80" text-anchor="middle">DOJ: {val}</text>'; OrgChart.templates.ana.field_3 = '<text class="field_3 style="font-size:14px;font-family=verdana, Arial !important;" fill="#ffffff" x="150" y="100" text-anchor="middle">Division: {val}</text>'; OrgChart.templates.ana.img_0 = '<image preserveAspectRatio="xMidYMid slice" xlink:href="{val}" x="-10" y="65" width="60" height="60"></image>'; var editForm = function () { this.nodeId = null; }; editForm.prototype.init = function (obj) { var that = this; this.obj = obj; this.editForm = document.getElementById("editForm"); this.nameInput = document.getElementById("Name"); this.titleInput = document.getElementById("Designation"); this.imgInput = document.getElementById("Photo"); this.dojInput = document.getElementById("DOJ"); this.divisionInput = document.getElementById("Division"); this.cancelButton = document.getElementById("close"); this.cancelButton.addEventListener("click", function () { that.hide(); }); }; editForm.prototype.show = function (nodeId) { this.nodeId = nodeId; var left = document.body.offsetWidth / 2 - 150; this.editForm.style.left = left + "px"; var node = chart.get(nodeId); if (!node) return; this.imgInput.src = node.Photo ? node.Photo : "#"; this.nameInput.innerHTML = node.Name ? node.Name : ""; this.titleInput.textContent = node.Designation ? node.Designation : ""; this.dojInput.textContent = node.DOJ ? node.DOJ : ""; this.divisionInput.textContent = node.Division ? node.Division : ""; this.editForm.style.display = "flex"; this.editForm.style.minHeight = "70vh"; this.editForm.style.background = "transparent"; OrgChart.animate(this.editForm, { opacity: 0 }, { opacity: 1 }, 300, OrgChart.anim.inOutSin); }; editForm.prototype.hide = function (showldUpdateTheNode) { this.editForm.style.display = "none"; this.editForm.style.opacity = 0; }; OrgChart.miniMap.opacity = 0.8; OrgChart.miniMap.border = '2px solid #039BE5'; OrgChart.miniMap.width = 80; OrgChart.miniMap.height = 75; OrgChart.miniMap.padding = 10; OrgChart.miniMap.top = '15px'; OrgChart.miniMap.position = { top: 'padding', left: 'padding', right: 'undefined', bottom: 'undefined' }; // *************************************************************************** chart = new OrgChart(document.getElementById('tree'), { lazyLoading:false, miniMap: true, mouseScrool: OrgChart.none, mouseScrool: OrgChart.action.scroll, padding: 70, enableSearch: true, layout: OrgChart.tree, align: OrgChart.ORIENTATION, toolbar: { layout: true, zoom: true, fit: true, expandAll: true, fullScreen:true }, menu: { export_pdf: { text: "Export PDF", icon: OrgChart.icon.pdf(24,24,"#7A7A7A"), onClick: pdf }, pdfPreview: { text: "PDF Preview", icon: OrgChart.icon.pdf(24, 24, "#7A7A7A"), onClick: preview } }, nodeBinding: { field_0: "Name", field_1: "Designation", field_2: "DOJ", field_3: "Division", img_0: "Photo" }, editUI: new editForm(), nodes: myNodes }); });
现有ASPX代码
<div id="editForm" style=" position:absolute; top:50%; left:50%; margin-top:-50px; margin-left:-50px; display:none; opacity:0; text-align:center; border: transparent; width:300px; background-color:#fff; z-index: 10000; border-radius:15px; filter:drop-shadow(5px 5px 5px #909090); "> <div class="card"> <div class="imgBx"> <img id="Photo" src="" /> </div> <div class="content"> <span id="close">X</span> <div class="details"> <h3 id="Name">Name</h3> <h3 id="Designation">Designation</h3> <div class="data"> <h4 id="DOJ"></h4><br /> <div class="span">Date Of Joining</div> <h4 id="Division"></h4><br /> <div class="span">Division</div> </div> </div> </div> </div> </div> <div id="tree" class="chart-container"></div>
解决方案
OrgChart自带的PDF导出仅针对组织结构图,自定义编辑表单是独立的HTML元素,需要通过前端库捕捉表单视觉内容并生成PDF。这里使用html2canvas(将HTML转为Canvas)和jsPDF(生成PDF)实现:
步骤1:添加库依赖
在页面中引入两个库的本地脚本(避免外链):
<script src="html2canvas.min.js"></script> <script src="jspdf.umd.min.js"></script>
步骤2:修改ASPX表单,添加导出按钮
在editForm的.content区域内添加导出按钮:
<div class="content"> <span id="close">X</span> <button id="exportFormBtn" style="margin:10px; padding:8px 16px; cursor:pointer;">导出表单为PDF</button> <!-- 原有内容保持不变 --> </div>
步骤3:修改JS代码,添加导出逻辑
在editForm.prototype.init方法中添加导出按钮的事件监听,并新增导出方法:
editForm.prototype.init = function (obj) { var that = this; this.obj = obj; this.editForm = document.getElementById("editForm"); this.nameInput = document.getElementById("Name"); this.titleInput = document.getElementById("Designation"); this.imgInput = document.getElementById("Photo"); this.dojInput = document.getElementById("DOJ"); this.divisionInput = document.getElementById("Division"); this.cancelButton = document.getElementById("close"); // 新增导出按钮引用 this.exportButton = document.getElementById("exportFormBtn"); this.cancelButton.addEventListener("click", function () { that.hide(); }); // 绑定导出按钮点击事件 this.exportButton.addEventListener("click", function () { that.exportFormToPdf(); }); }; // 新增PDF导出方法 editForm.prototype.exportFormToPdf = function () { const formElement = this.editForm; // 用html2canvas渲染表单 html2canvas(formElement, { scale: 2, // 提高导出清晰度 useCORS: true, // 处理跨域图片(若图片来自外部域名) logging: false }).then(canvas => { // 初始化jsPDF const pdf = new jspdf.jsPDF('p', 'mm', 'a4'); const imgWidth = 210; // A4宽度(mm) const imgHeight = canvas.height * imgWidth / canvas.width; let position = 0; // 将Canvas添加到PDF pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, imgWidth, imgHeight); // 若表单内容过长,自动分页 let heightLeft = imgHeight; while (heightLeft >= 297) { // A4高度(mm) position = heightLeft - imgHeight; pdf.addPage(); pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= 297; } // 保存PDF,文件名包含节点ID pdf.save(`employee_form_${this.nodeId}.pdf`); }).catch(err => { console.error('导出失败:', err); }); };
关键说明
- 若表单中的图片来自外部域名,需确保服务器配置了CORS允许跨域访问,否则
html2canvas无法渲染图片 - 调整
scale参数可控制导出清晰度,数值越高越清晰但文件越大 - 可根据表单实际尺寸修改PDF的页面尺寸和图片位置参数
内容的提问来源于stack exchange,提问作者Raj Shukla
相关产品推荐
相关产品推荐

