原生JS实现文件自定义位置盖章功能并导出PDF

pdf.js预览pdf文件并且使用进行图片签章功能 来自这位大佬:https://blog.youkuaiyun.com/a15297701931/article/details/135062029。2.pdf.js中的getDocument方法使用的是data,pdf的arraybuffer格式。1.删减了放缩功能,放开了调整图章大小的功能,前者和后者功能冲突。3.下面的/deep/调整成了::v-deep。首先按照上面这个链接引入对应包。 阅读详情

原生JS实现文件自定义位置盖章功能并导出PDF

实现原理

在需要签章的文件上面创建一个div,可以通过移动这个div来确定签章位置,然后在通过获取这个位置把章子替换到这,并导出PDF,可以多次盖章!

实现截图

在这里插入图片描述

代码实现

废话不多说,直接上全部代码,不懂的看注释或底下评论。。。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="container">
      <div class="box">
        <div class="imageList">
          <img
            class="table"
            src="./img/工程表(纵向单页).png"
            alt=""
            srcset=""
          />
        </div>
        <button class="setSign" style="position: fixed; top: 10px; left: 10px">
          设置签章点位
        </button>
        <div style="position: fixed; top: 50px; left: 10px">
          <!-- <button class="determineSign">确定签章</button> -->
          选择公章:
          <select id="select">
            <option value="./img/signImage/公章1.png">公章1</option>
            <option value="./img/signImage/公章2.png">公章2</option>
          </select>
        </div>
        <button class="getPoint" style="position: fixed; top: 90px; left: 10px">
          确定盖章
        </button>
      </div>
    </div>
  </body>
  <script>
    //图片表格是纵向还是横向
    let hasPortrait = true; //默认是纵向
    // 给图片设置宽高(A4纸的宽高)
    let a4Size = {
      w: (595.28 * 4) / 3,
      h: (841.89 * 4) / 3,
    };
    //签章的宽高
    let signSize = {
      w: 140,
      h: 140,
    };
    //签章确定后的点位
    let signPoint = {
      left: "",
      top: "",
    };
    initPdf();

    //设置点击事件
    //生成签章
    document.querySelector(".setSign").addEventListener("click", function () {
      setSign();
    });
    //获取点位
    document.querySelector(".getPoint").addEventListener("click", function () {
      let signDom = document.querySelector(".sign");
      getSignPoint(signDom);
      console.log(signPoint);
      determineSign();
    });
    //确定盖章
    function determineSign() {
      let myselect = document.getElementById("select");
      let url = myselect.options[myselect.selectedIndex].value;
      //创建img
      let signImg = document.createElement("img");
      console.log(url);
      signImg.src = url;
      let option = {
        width: signSize.w + "px",
        height: signSize.h + "px",
        position: "absolute",
        top: signPoint.top,
        left: signPoint.left,
        zIndex: 999,
      };
      for (const key in option) {
        if (Object.hasOwnProperty.call(option, key)) {
          const element = option[key];
          signImg.style[key] = element;
        }
      }
      //删除签章位置样式
      document.querySelector(".sign").remove();
      document.querySelector(".imageList").appendChild(signImg);
    }
    //生成签章的方法
    function setSign() {
      //获取生成签章位置的容器dom
      let imageListDom = document.querySelector(".imageList");
      //创建一个签章div
      let signDiv = document.createElement("div");
      //设置样式
      let option = {
        backgroundColor: "transparent",
        width: `${signSize.w}px`,
        height: `${signSize.h}px`,
        position: "absolute",
        color: "red",
        textAlign: "center",
        lineHeight: `${signSize.h - 10}px`,
        border: "3px dashed red",
        borderRadius: "50%",
        boxSizing: "border-box",
        userSelect: "none",
        zIndex: 999,
      };
      for (const key in option) {
        if (Object.hasOwnProperty.call(option, key)) {
          const element = option[key];
          signDiv.style[key] = element;
        }
      }
      signDiv.className = "sign";
      signDiv.innerHTML = "签章位置";
      imageListDom.appendChild(signDiv);
      //设置移动事件
      addDrag(signDiv);
    }
    //给生成的签章设置移动事件方法
    function addDrag(dom) {
      //给签章设置鼠标移动样式
      dom.style.cursor = "move";
      let initX = null;
      let initY = null;
      //获取初始点击的位置
      dom.addEventListener("mousedown", mouseDownClick);
    }
    //签章移动事件
    function mouseDownClick(e) {
      let dom = document.querySelector(".sign");
      //获取该dom距离可视宽度的距离
      initX = e.pageX - dom.offsetLeft;
      initY = e.pageY - dom.offsetTop;
      //鼠标移动事件设置移动位置
      document.addEventListener("mousemove", moveEle);
      function moveEle(e) {
        let x = e.pageX - initX;
        let y = e.pageY - initY;

        // 签章边界
        if (x < 0) x = 0;
        if (y < 0) y = 0;
        let maxL = (hasPortrait ? a4Size.w : a4Size.h) - signSize.w;
        if (x > maxL) x = maxL;
        let maxT = (hasPortrait ? a4Size.h : a4Size.w) - signSize.h;
        if (y > maxT) y = maxT;

        dom.style.top = y + "px";
        dom.style.left = x + "px";
      }
      // 鼠标松开移出方法
      document.addEventListener("mouseup", function () {
        document.removeEventListener("mousemove", moveEle);
      });
    }
    //获取签章点位
    function getSignPoint(dom) {
      signPoint.left = dom.style.left;
      signPoint.top = dom.style.top;
    }
    //处理图片,是纵向还是横向
    function initPdf() {
      //获取表格图片盒子dom
      let imgBoxDom = document.querySelector(".box");
      let imgListDom = document.querySelector(".imageList");
      //获取图片的dom
      let imgDom = document.querySelector("img");
      let imgInfo = {
        width: imgDom.naturalWidth, //图片真实宽度
        height: imgDom.naturalHeight, //图片真实高度
      };
      // 判断是横向还是纵向
      hasPortrait = imgInfo.width < a4Size.w;
      imgBoxDom.style.width = (hasPortrait ? a4Size.w : a4Size.h) + "px";
      imgBoxDom.style.height = (hasPortrait ? a4Size.h : a4Size.w) + "px";
      imgListDom.style.width = (hasPortrait ? a4Size.w : a4Size.h) + "px";
      imgListDom.style.height = (hasPortrait ? a4Size.h : a4Size.w) + "px";
    }
  </script>
  <style>
    .box {
      position: relative;
      width: 100%;
      box-shadow: 0 0 4px 0 #ccc;
      margin: 0 auto;
    }
    .box .imageList {
      background-color: white;
      position: absolute;
      top: 0;
      left: 0;
      overflow: hidden;
    }
    .imageList .table {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      margin: auto;
    }
  </style>
</html>

文件导出功能

看原来的文章,地址:Vue中将页面导出为PDF

前端拖拽事件解析-react实现拖拽效果demo 前言 在平时开发中会有一些涉及到通过拖拽效果完成的业务需求,那么我们就需要了解和学习拖拽相关的知识,在html5中就有原生的拖拽api,下面就来使用这些api实现一个灵活拖拽的demo。 拖拽流程 简单来说完成拖拽一共需要三步: 开始拖拽 -> 拖拽中 -> 结束拖拽。 在这些步骤中又会有许多更细节的步骤需要处理,完整流程如下: 1、设置指定元素为可拖拽元素(使用draggable属性,只有设置了draggable属性,元素才可以被拖动) 2、点击拖拽元素开始进行拖拽并监听拖拽开始事件(设置拖拽 阅读详情

相关推荐

模板驱动文档自动化:零代码实现业务人员自助生成PDF

模板驱动文档自动化是一种将内容与格式物理分离的确定性文档生成范式,其核心原理是通过强类型占位符(如{{client_name}})、条件区块和循环结构,在可视化编辑器中构建可复用、可版本化、可审计的文档模具。相比AI生成易导致合规风险与责任模糊,也区别于代码定制带来的高维护成本,该技术以零代码为门槛,赋予市场、销售、HR等业务人员自主生成合同、报价单、对账单等标准化PDF的能力,显著降低人工错误率并加速审批闭环。典型应用场景包括SaaS服务协议批量签署、动态报价单实时生成、多客户财务对账单自动化输出等,本质

weixin_34198453的博客 374

关于前端PDF显示和盖章(vue)

PDF https://www.jianshu.com/p/94cf6ddcb299 https://segmentfault.com/a/1190000016963084

Harrietjia的博客 1万+

Power BI分页报表实战指南:从SSRS引擎原理到PDF合规输出

分页报表是Power BI中面向打印归档的结构化文档生成技术,其底层基于SQL Server Reporting Services(SSRS)服务器端渲染引擎,与Power BI Desktop的交互式HTML5渲染有本质区别。它通过预定义页面布局、严格分页控制和VB.NET风格表达式,确保PDF/Excel导出100%保形,满足财务对账单、发票、审计报告等法务与监管场景的格式刚性要求。关键技术价值在于支持参数化筛选、自动邮件推送、Premium容量调度及DirectQuery实时数据绑定。本文聚焦Pagi

weixin_30820077的博客 482

PDF电子签章,用鼠标拖动印章到指定的位置, 一种在网页PDF中电子签章定位方法

一、前言 在开发PDF电子签名时,需要在用pdf.js显示pdf文件,用shu'bi

ysjydss的博客 8715

模板驱动型文档自动化:让Word/PDF生产变填空题

文档自动化本质是将重复性内容生成从人工操作升级为规则化、可验证的数字流程。其核心原理在于通过结构化模板封装样式、逻辑与数据映射关系,实现‘一次配置、多次复用、零代码维护’的技术价值。相比AI生成易出事实性错误、代码驱动依赖开发响应慢,模板驱动兼顾合规性、业务自主性与实施效率,广泛应用于法务合同、HR制度、医疗文书、政府标书等强结构、高合规场景。本文聚焦Sqribble平台,详解模板四层架构(视觉/结构/逻辑/集成)与字段驱动式工作流设计。

weixin_30457551的博客 335

Kimi K2.5驱动的Vibe Coding报价系统实战

报价系统本质是受控决策链,而非简单问答——它需融合产品参数、成本数据、合规条款与销售策略,在强约束下生成可盖章交付的正式文件。大模型在该场景的价值,不在于通用推理能力,而在于能否稳定解析自然语言需求、精准召回结构化知识、严格遵循业务规则并输出可审计结果。Kimi K2.5凭借高确定性输出、优异的中文术语理解与长上下文关键信息召回能力,成为工业品垂直报价的理想推理引擎;Vibe Coding则通过JSON Schema化规则定义与提示词协议,让销售主管等非技术人员可直接修改毛利率、运费、质保等逻辑,实现业务知

weixin_34293141的博客 436

PDF 批量盖骑缝章怎么弄?

招投标标书、工程合同、检测报告、项目资料大多是多页 PDF,业务上经常需要加盖骑缝章,用来防止页面抽换、保证文件完整性。很多小伙伴踩坑:在线工具要上传文件怕泄密;WPS 只能单份操作、批量很麻烦;Adobe 操作繁琐不适合大批量文档;打印纸质盖章再扫描,耗时耗材。。本文横向对比各类方案优缺点,重点讲解适合批量、注重文件保密场景的方案。重要说明:文中所有视觉电子骑缝章仅为图片签章,不等于具备法律效力的 CA 可靠电子签名;如需满足《电子签名法》合规签约需求,建议搭配正规数字证书使用。

qq_54933350的博客 224

电子印章js实现实例.zip

这是电子印章js插件,直接通过js实现功能..

模板驱动文档自动化:零代码生成PDF的工程实践

文档自动化是企业提升运营效率的基础技术能力,其核心在于将重复性文档生产从人工操作升级为结构化、可复用、可审计的工程流程。基于模板驱动(Template-Driven)原理,系统通过可视化绑定数据源与预设排版骨架,实现确定性输出,兼顾合规性与业务自主权;相比规则脚本或AI生成,它在法律文书、财务对账、客户报告等强格式场景中展现出更高稳定性与落地成熟度。技术价值体现在降低80%手工耗时、消除格式错漏、统一品牌表达,并天然支持条件渲染、动态图表、跨页排版等专业需求。本文以Sqribble为典型平台,详解零编码(N

weixin_30654583的博客 343

在PDF文件固定坐标插入图片(类似于签名)

在PDF文件的固定坐标位置上插入图片,图片支持jpg、bmp、pdf等格式,类似于签名,将手写签名扫描为图片,插入到PDF文件中去。

PDFSignjs是一个用于在浏览器中签名PDF文档的JavaScript库

PDFSign.js 是一个用于在浏览器中签名 PDF 文档的 JavaScript 库。签名只在浏览器中进行,且不会通过网络发送私钥或密码。

模板驱动型文档自动化:零代码实现动态PDF生成

文档自动化是企业提升内容生产效率的关键技术,其核心在于将固定结构与可变数据解耦。模板驱动型自动化不同于传统邮件合并或静态样式套用,它基于语义区块、条件逻辑与多源数据绑定,实现真正意义上的‘一次设计、千人千面’。该技术依托无代码逻辑画布、动态字段渲染和协议无关的数据桥接能力,显著降低业务人员使用门槛,广泛应用于投标书、合同、课纲、诊断报告等标准化文档场景。本文聚焦Sqribble平台实践,详解如何构建具备条件判断、样式继承与实时数据同步能力的智能模板。

weixin_33896726的博客 374

基于yolo11的BGA图像目标检测

15.YOLOv8的n/s版本(如YOLOv8n-1280),或通过TensorRT量化压缩模型。3.使用自适应batch_size(如根据GPU显存动态调整),推荐16-32。为采集分辨率整数倍(如原图2592×1944,训练时缩放为640×480),保持宽高比。14.采用余弦退火学习率(cos_lr)和早停(patience=50),防止过拟合。1.模型标注后,少量标注全部人工校验,大量数据抽检,部分人工检验。13.部署模型后持续收集困难样本(如模棱两可的预测结果),定期迭代更新模型。

qq_47798402的博客 1205

模板驱动型文档自动化:让Word/PDF具备React式组件能力

文档自动化本质上是将非结构化内容生产升级为可编程、可复用、可验证的工程实践。其核心在于解耦文档格式与业务逻辑,通过声明式模板、结构化内容注入和跨源数据绑定,实现动态章节生成与条件化段落渲染。相比传统‘复制粘贴式模板’,该技术显著降低人为错误率,提升合规性与版本可控性,广泛应用于合同生成、客户方案、政策文件等高频标准化场景。Sqribble等现代工具以零代码编辑器、原生PDF质量控制和企业级权限模型,使法务、售前、HR等非技术人员也能安全高效地维护文档逻辑,真正实现‘文档即API响应’的工程化范式。

weixin_30753873的博客 376

压电传感器信号放大难题?用运放设计电荷放大器的5个关键步骤

本文详细解析了压电传感器信号放大难题,并提供了用运放设计电荷放大器的5个关键步骤。从电压放大到电荷放大的范式转换,到运放选型、反馈网络设计、PCB布局及频响特性验证,帮助工程师解决工业自动化中的信号衰减问题,提升测量精度和稳定性。

weixin_27303545的博客 447

用STM32的SPI模式2搞定SSI绝对值编码器通信(附完整代码与避坑点)

本文详细解析了如何使用STM32的SPI模式2实现SSI绝对值编码器通信,包括硬件设计、SPI配置、数据处理算法及稳定性优化技巧。通过完整的代码示例和避坑指南,帮助工程师解决时序匹配、数据解析等常见问题,提升工业自动化系统中的编码器通信可靠性。

weixin_27252001的博客 264

模板驱动型文档自动化:结构化内容复用的技术实现

文档自动化是企业提升内容生产效率的关键技术路径,其核心在于将重复性文档生成从人工操作升级为可编程、可验证、可审计的工程流程。模板驱动模式通过声明式结构定义、占位符映射与多源数据契约,实现内容与样式的解耦,确保品牌一致性与法律合规性;相比AI生成,它以确定性逻辑替代概率性输出,在金融、医疗、政务等强监管场景中保障格式零偏差与数据溯源能力。该技术广泛应用于销售提案、合规报告、客户服务简报等结构清晰、高频批量的业务文档场景,本质是面向结构化内容复用的流水线系统。

duiker 480

从寄存器到驱动:深入解读RFSoC RF-ADC阈值与校准API的底层逻辑

本文深入解析Xilinx RFSoC中RF-ADC的阈值检测与校准API的底层逻辑,涵盖寄存器映射、驱动实现及Gen3增强功能。通过详细代码示例和寄存器操作流程,揭示如何精准控制信号阈值检测与校准时序,提升系统稳定性与性能。特别探讨RF数据转换器在无线通信和雷达信号处理中的关键应用。

weixin_30552811的博客 687

模板驱动的零代码文档自动化:业务人员自助生成合规PDF

文档自动化是企业提效降错的关键技术路径,其核心在于解耦内容与形式——通过结构化模板定义静态框架,绑定动态数据字段实现精准填充。相比AI生成易引发合规风险、代码定制维护成本高,模板驱动方案以强类型占位符、可视化条件逻辑和内置校验机制,保障法律效力与版本可控性。它天然适配合同、发票、投标书、对账单等高频标准化文档场景,让市场、销售、法务等非技术人员无需编码即可自主管理文档产出。Sqribble正是这一范式的典型实践,聚焦‘确定性交付’而非‘智能幻觉’,将文档从人工劳动密集型任务升级为可复用、可审计、可演进的企业

weixin_34414650的博客 369

华为项目TR5评审后发现了重大缺陷的应急处理经验

华为TR5评审后发现重大缺陷时,启动分级应急机制:1)缺陷分级:按严重性(致命/严重/一般)评估影响;2)应急响应:跨部门会议制定方案,冻结生产并调配资源;3)根因修复:通过RCA定位问题,设计变更后回归测试;4)变更管理:评审修复影响,调整发布策略;5)持续改进:记录缺陷闭环,优化流程。案例显示,软件闪退问题通过热修复补丁和代码重构解决。关键工具包括Jira、FMEA等,确保缺陷在量产前拦截,降低风险。

从技术实践立足,从项目管理方法论延伸思考 1069

OpenHarmony自定义Launcher

OpenHarmony源码版本:4.0release开发板:DAYU / rk3568DevEco Studio版本:4.0.0.600切换分支为OpenHarmony-4.0-Release,并下载源码。

Abner_Crazy的博客 1630

Sqribble深度解析:模板驱动的文档自动化出版流水线

电子书排版与PDF出版是内容创作者面临的基础工程问题,其本质是将非结构化文本转化为符合印刷规范、品牌统一、语义清晰的静态交付物。核心原理在于内容结构化、样式原子化与布局规则化,技术价值体现在消除人工排版的不确定性、压缩交付周期至分钟级,并保障跨设备渲染一致性。典型应用场景包括SaaS营销手册、企业知识沉淀、讲师课件交付等高频标准化文档生产。Sqribble并非AI写作工具,而是聚焦于‘内容装盒’环节的云原生出版流水线,以模板为契约、以规则为引擎,实现零容错的确定性输出。

wentao365的专栏 480

2026年紫光同创数字IC笔试试卷带答案

FPGA基础知识与设计要点摘要 本文围绕FPGA与数字IC设计核心概念,通过单选题、波形分析题、多选题和简答题形式,系统梳理了以下关键知识点: FPGA基础架构 查找表(LUT)是实现组合逻辑的基本单元(题1) CLB包含LUT、触发器和进位链,后者加速算术运算(题6,10) 布局布线优化是减少关键路径延迟的核心方法(题7) 时序分析要点 建立时间(时钟沿前数据需稳定)与保持时间(时钟沿后需保持)的定义(题2,简答1) 亚稳态成因及两级同步器处理跨时钟域信号的方法(多选题1,波形题5) 特殊设计技术 异步复

Open 114

模板驱动型文档自动化:告别手工填空,实现合规高效生成

文档自动化是企业提升运营效率的关键技术路径,其核心在于将结构化文档生产从人工操作升级为确定性、可复用的智能流程。区别于AI生成的不可控性和低代码平台的样式失真问题,模板驱动型文档自动化依托静态框架、动态逻辑与数据契约三层架构,确保格式精准、条款合规、样式保真。该技术显著降低人为错误率,缩短销售报价、合同生成、客户报告等高频场景交付周期,并天然支持多系统数据集成与品牌视觉统一。本文聚焦Sqribble平台实践,详解如何通过Word原生模板构建具备条件判断、循环渲染与跨源绑定能力的智能文档流水线。

【洪波@阿里云】 618

OpenCV实现物体尺寸的测量

物体尺寸测量的思路是找一个确定尺寸的物体作为参照物,根据已知的计算未知物体尺寸。如下图所示,绿色的板子尺寸为220*300(单位:毫米),通过程序计算白色纸片的长度。

qq_53545309的博客 9157

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

模板驱动文档自动化:零代码实现业务人员自助生成合同与报表

文档自动化是企业提效降本的关键环节,其本质在于将内容与格式解耦,通过结构化模板实现确定性输出。相比AI生成易引发合规风险、代码定制推高维护成本,模板驱动方案以强类型占位符、可视化条件逻辑和静态/动态分层设计为核心,保障法律条款一致性、数据可追溯性与版本可控性。该技术广泛应用于销售合同、财务对账单、HR Offer等高频文档场景,尤其适合市场、法务、HR等非技术人员快速上手。Sqribble作为典型代表,聚焦零代码、业务自助、模板即资产三大特性,让文档从人工填表升级为工作流中枢。

weixin_33744141的博客 393

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: Vue中将页面导出为PDF
下一篇: Vue移动框鼠标拖拽自定义指令
龟中的程序员
博客等级 码龄7年 328粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龟中的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值