网站建设如何避免陷入模仿误区企业网站怎么扣费的
网站建设如何避免陷入模仿误区,企业网站怎么扣费的,anivia wordpress,黄埔网站建设价格PDF 拖拽盖章平台在 AI 能基本实现百分之九十以上的前端代码时#xff0c;不知道写这种前端工具还有没有人看#xff1f;我用相对详细的方式#xff0c;完整拆解一个「PDF 拖拽盖章平台」的实现过程#xff0c;覆盖多页渲染、拖拽盖章、撤销/还原、导出图片与 PDF、性能优化…PDF 拖拽盖章平台在 AI 能基本实现百分之九十以上的前端代码时不知道写这种前端工具还有没有人看我用相对详细的方式完整拆解一个「PDF 拖拽盖章平台」的实现过程覆盖多页渲染、拖拽盖章、撤销/还原、导出图片与 PDF、性能优化懒渲染等关键环节。示例包含 React 与 Vue3 两套实现逻辑一致、写法不同。目标与约束目标支持上传多页 PDF。在预览区域拖拽印章支持骑缝章。支持撤销 / 还原。支持导出图片和 PDF。大文件也能流畅渲染不“卡成 PPT”。主要约束浏览器对 canvas 尺寸有上限不同浏览器略有差异。长图导出容易失败需要降级方案。大 PDF 一次性渲染会阻塞主线程。核心思路统一坐标系 多页 canvas这里的关键是把整份 PDF 当成一张“虚拟长画布”。每一页各有一个canvas显示真实页面内容。所有盖章坐标都以“整份文档坐标系”为准。每页只要知道自己在整份文档中的位置pagePositions就能把盖章正确映射回去。这样做有两个好处骑缝章天然支持印章跨页坐标也能跨页。导出更稳定导出时可自由选择“整图”或“逐页”。核心依赖pdfjs-dist解析与渲染 PDFpdf-lib导出带印章的 PDF图片型 PDF安装示例pnpm add pdfjs-dist pdf-libPDF 解析与页面尺寸获取先读取文档并计算每页尺寸。这里只取尺寸不渲染避免一开始就卡死。const loadingTask pdfjsLib.getDocument({ data: arrayBuffer }); const pdf await loadingTask.promise; const pages []; for (let pageIndex 1; pageIndex pdf.numPages; pageIndex 1) { const page await pdf.getPage(pageIndex); const viewport page.getViewport({ scale: PAGE_SCALE }); pages.push({ width: viewport.width, height: viewport.height }); }拿到pages后就能计算整份文档尺寸和每页偏移量。const docSize useMemo(() { const width Math.max(...pdfPages.map((page) page.width)); const height pdfPages.reduce( (sum, page, index) sum page.height (index pdfPages.length - 1 ? PAGE_GAP : 0), 0 ); return { width, height }; }, [pdfPages]); const pagePositions useMemo(() { let offsetY 0; return pdfPages.map((page, index) { const pos { x: (docSize.width - page.width) / 2, y: offsetY }; offsetY page.height (index pdfPages.length - 1 ? PAGE_GAP : 0); return pos; }); }, [pdfPages, docSize.width]);解释docSize是整个虚拟画布大小。pagePositions是每页在虚拟画布中的左上角坐标。预览区滚动与布局多页 PDF 不可能全部撑开所以预览区必须做“内部滚动”。.pdf-stage { max-height: clamp(520px, 70vh, 820px); overflow: auto; }这样页面滚动只发生在 PDF 区域内用户体验会舒服很多。拖拽盖章实现坐标换算拖拽时需要把屏幕坐标转换成“文档坐标”。关键点就是overlay的矩形位置。const rect overlayRef.current.getBoundingClientRect(); const x event.clientX - rect.left - template.width / 2; const y event.clientY - rect.top - template.height / 2; const nextStamp { instanceId: buildInstanceId(template.id), src: template.src, width: template.width, height: template.height, x: clamp(x, 0, docSize.width - template.width), y: clamp(y, 0, docSize.height - template.height), };实时拖动 撤销栈拖动过程中只更新“临时状态”拖动结束再写入历史栈保证撤销栈干净。// 实时更新 updateLiveStamps((prev) prev.map(...)); // 拖动结束写入历史 if (drag.moved) commitStamps(liveStampsRef.current);好处撤销时不是“细碎步进”而是一次拖动一个记录。性能优化懒渲染 队列渲染 PDF 是最容易卡顿的地方。解决方案是IntersectionObserver只有当页面进入视口时才渲染。渲染队列保证渲染顺序不并发拖慢主线程。预渲染前两页首屏更快。const observer new IntersectionObserver( (entries) { entries.forEach((entry) { if (!entry.isIntersecting) return; const index Number(entry.target.dataset.index); queueRender(index); }); }, { root: stageElement, rootMargin: 240px 0px, threshold: 0.1 } );渲染队列逻辑const renderPage async (index) { const page await pdfDoc.getPage(index 1); const viewport page.getViewport({ scale: PAGE_SCALE }); const canvas canvasRefs.current[index]; const ctx canvas.getContext(2d); canvas.width viewport.width; canvas.height viewport.height; await page.render({ canvasContext: ctx, viewport }).promise; };这样渲染压力被“分散到用户滚动过程”不会一次性卡死。导出图片长图 逐页降级导出长图时浏览器对 canvas 尺寸限制很严格。如果文档太长直接导出会失败因此需要检测并降级。const isTooLarge docSize.width MAX_EXPORT_DIMENSION || docSize.height MAX_EXPORT_DIMENSION || docSize.width * docSize.height MAX_EXPORT_PIXELS; if (isTooLarge) { // 改为逐页导出 }逐页导出时要把全局印章坐标换算到当前页坐标这样骑缝章也不会丢。导出 PDF完整文件导出 PDF 用pdf-lib做合成每一页画布含印章转为 PNG。插入到新 PDF 页。生成 PDF 并下载。const pdfDocument await PDFDocument.create(); const pngImage await pdfDocument.embedPng(pngBytes); const pdfPage pdfDocument.addPage([page.width, page.height]); pdfPage.drawImage(pngImage, { x: 0, y: 0, width: page.width, height: page.height });下载逻辑const pdfBytes await pdfDocument.save(); const blob new Blob([pdfBytes], { type: application/pdf }); const url URL.createObjectURL(blob); link.download 盖章结果-${new Date().toISOString().slice(0, 10)}.pdf; link.href url; link.click();导出的 PDF 为“图片型 PDF”兼容性高但文字不可搜索。如果要保留矢量文字需要更复杂的“原 PDF 叠加”方案。扩展方向矢量 PDF 导出直接在原 PDF 叠加印章更复杂但可保留文字可搜索。通用库封装提炼核心逻辑为coreReact/Vue 只是适配层。企业场景扩展模板库、权限管理、批量盖章。如果你准备上线到业务系统建议在此基础上增加盖章操作日志导出前的预检查页数、尺寸失败重试和导出进度提示这样体验会更接近商业级工具。