OBJ数据生成PDF(Workshop):用户对象选择与导出功能咨询
实现OBJ对象选择、新建与PDF导出的方案
一、UI交互层实现
先搭建基础交互界面,让用户能直观选择目标对象,并触发新建/导出操作:
- 用多选复选框组或下拉选择器展示所有OBJ对象列表,每个选项绑定对象的唯一ID或索引,方便后续获取对应数据
- 放置两个操作按钮:「创建新OBJ文件」和「导出所选为PDF」,分别绑定对应的处理函数
示例HTML结构:
<div class="obj-selector"> <h3>选择目标OBJ对象</h3> <div id="obj-list"></div> </div> <div class="actions"> <button id="create-obj-btn">创建新OBJ文件</button> <button id="export-pdf-btn">导出所选为PDF</button> </div>
用JavaScript动态渲染对象列表:
// 模拟存储的OBJ对象数据 const objDataList = [ { id: 1, name: "模型A", content: "# OBJ模型A数据..." }, { id: 2, name: "模型B", content: "# OBJ模型B数据..." } ]; // 渲染选择列表 const objListEl = document.getElementById('obj-list'); objDataList.forEach(obj => { const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.value = obj.id; checkbox.id = `obj-${obj.id}`; const label = document.createElement('label'); label.htmlFor = checkbox.id; label.textContent = obj.name; objListEl.appendChild(checkbox); objListEl.appendChild(label); objListEl.appendChild(document.createElement('br')); });
二、创建新OBJ文件的逻辑
点击「创建新OBJ文件」按钮时,完成以下步骤:
- 弹出输入框让用户输入新OBJ的名称
- 生成默认的OBJ模板内容(比如包含基础的顶点、面结构注释)
- 把新OBJ数据添加到对象列表,同时触发本地下载
示例实现:
document.getElementById('create-obj-btn').addEventListener('click', () => { const objName = prompt("请输入新OBJ文件名称:"); if (!objName) return; // 生成默认OBJ模板 const defaultObjContent = `# ${objName} 模型 v 0.0 0.0 0.0 v 1.0 0.0 0.0 v 1.0 1.0 0.0 v 0.0 1.0 0.0 f 1 2 3 f 1 3 4`; // 创建Blob并触发下载 const blob = new Blob([defaultObjContent], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${objName}.obj`; a.click(); URL.revokeObjectURL(url); // 可选:将新对象添加到列表 const newObj = { id: Date.now(), name: objName, content: defaultObjContent }; objDataList.push(newObj); // 重新渲染列表(这里可以优化为只添加新项,不用全量渲染) objListEl.innerHTML = ''; objDataList.forEach(obj => { /* 重复之前的渲染逻辑 */ }); });
三、导出所选对象为PDF的逻辑
导出PDF需要分两种场景处理:纯文本OBJ数据导出,或可视化模型导出。
场景1:导出OBJ文本内容到PDF
直接将选中对象的OBJ文本内容写入PDF,适合查看源码的需求:
import jsPDF from 'jspdf'; // 需引入jsPDF库 document.getElementById('export-pdf-btn').addEventListener('click', () => { // 获取选中的对象ID const selectedIds = Array.from(document.querySelectorAll('input[type="checkbox"]:checked')) .map(checkbox => parseInt(checkbox.value)); if (selectedIds.length === 0) { alert("请至少选择一个OBJ对象"); return; } // 获取选中对象的内容 const selectedContents = objDataList .filter(obj => selectedIds.includes(obj.id)) .map(obj => `--- ${obj.name} --- \n${obj.content}`) .join('\n\n'); // 生成PDF const doc = new jsPDF(); doc.setFontSize(12); // 处理长文本自动换行 const lines = doc.splitTextToSize(selectedContents, 180); doc.text(lines, 10, 10); doc.save('selected-obj-files.pdf'); });
场景2:导出OBJ模型的可视化渲染图到PDF
如果需要将OBJ模型渲染成图像再导出PDF,需要用到3D渲染库(如Three.js):
- 用Three.js加载选中的OBJ模型,渲染到Canvas
- 将Canvas内容转为图片,插入到PDF中
示例核心代码:
import * as THREE from 'three'; import { OBJLoader } from 'three/addons/loaders/OBJLoader.js'; import jsPDF from 'jspdf'; async function renderObjToCanvas(objContent) { const canvas = document.createElement('canvas'); canvas.width = 800; canvas.height = 600; const renderer = new THREE.WebGLRenderer({ canvas }); const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, canvas.width/canvas.height, 0.1, 1000); // 添加光源 scene.add(new THREE.AmbientLight(0xffffff)); // 加载OBJ内容 const loader = new OBJLoader(); const object = loader.parse(objContent); scene.add(object); // 调整相机位置 const box = new THREE.Box3().setFromObject(object); const center = box.getCenter(new THREE.Vector3()); const size = box.getSize(new THREE.Vector3()); const maxDim = Math.max(size.x, size.y, size.z); const cameraZ = maxDim * 1.5; camera.position.set(center.x, center.y, cameraZ); camera.lookAt(center); // 渲染 renderer.render(scene, camera); return canvas.toDataURL('image/png'); } // 导出按钮绑定逻辑 document.getElementById('export-pdf-btn').addEventListener('click', async () => { const selectedIds = Array.from(document.querySelectorAll('input[type="checkbox"]:checked')) .map(checkbox => parseInt(checkbox.value)); if (selectedIds.length === 0) { alert("请至少选择一个OBJ对象"); return; } const doc = new jsPDF('landscape'); let yPos = 10; for (const id of selectedIds) { const obj = objDataList.find(o => o.id === id); const imgData = await renderObjToCanvas(obj.content); // 插入图片到PDF,调整尺寸适配页面 doc.addImage(imgData, 'PNG', 10, yPos, 270, 200); doc.text(obj.name, 10, yPos - 5); yPos += 210; // 超过页面高度时添加新页 if (yPos > 280) { doc.addPage(); yPos = 10; } } doc.save('obj-models-preview.pdf'); });
四、关键注意事项
- 确保用户选择验证:导出前检查是否有选中对象,避免空导出
- 处理大文件:如果OBJ模型过大,渲染时要考虑性能优化(比如简化模型、分批渲染)
- 兼容性:jsPDF和Three.js需要注意浏览器兼容性,针对旧浏览器可能需要降级处理
内容的提问来源于stack exchange,提问作者Foundry_Users
相关产品推荐
相关产品推荐

