项目场景:

项目场景:系统新增打印发货单功能


开工开工

两种方式引入依赖包

npm install html2canvas jspdf --save
yarn add html2canvas jspdf --save

直接上代码:

提示:项目引入组件较多,自行理解代码即可。注意opacity: 0 处为点睛之笔。防止拷贝的dom覆盖当前样式故隐藏,display:none是不行的,pdf会白纸的哦!

import React, { createRef, LegacyRef } from 'react';
import { Modal, Table, Button } from 'antd';
import JsPDF from 'jspdf';
import html2Canvas from 'html2canvas';
//moment依赖
import moment from 'moment';export default class DeliverGoodsModal extends React.Component<any, any> {constructor(props, ctx) {super(props);this.state = {loading: false,loadingDown: false,deliverVisible: false};}_columns = [{title: 'SKU编码',dataIndex: 'name',key: 'name',render: (text) => <span>{text}</span>},{title: '商品名称',dataIndex: 'sss',key: 'sss',width: 280,render: (text) => <span>{text}</span>},{title: '规格',dataIndex: 'address',key: 'address'},{title: '采购数量',dataIndex: 'ages',key: 'ages'},{title: '已发数量',dataIndex: 'age',key: 'age'},{title: '本地发货数',dataIndex: 'agesss',key: 'agesss'},{title: '单价',dataIndex: 'agess',key: 'agess'},{title: '金额小计',dataIndex: 'agessx',key: 'agesssx'}];render() {const pdfs = createRef();const handlePrint = (isPrint: boolean) => {let targetDom: any = pdfs.current;// 获取节点高度,后面为克隆节点设置高度。let height = targetDom.height;// 克隆节点,默认为false,不复制方法属性,为true是全部复制。let cloneDom = targetDom.cloneNode(true);// 设置克隆节点的css属性,因为之前的层级为0,我们只需要比被克隆的节点层级低即可。//cloneDom.style.backgroundColor = 'red';cloneDom.style.position = 'absolute';cloneDom.style.top = '0';cloneDom.style.index = '-1';cloneDom.style.height = height;// 将克隆节点动态追加到body后面。document.getElementById('pdf-con')?.appendChild(cloneDom);// 插件生成base64img图片。html2Canvas(cloneDom, {useCORS: true,// 画布开始渲染的y坐标位置y: 0}).then((canvas) => {// console.log('canvas', canvas);let contentWidth = canvas.width;let contentHeight = canvas.height;// 一页pdf显示html页面生成的canvas高度;let pageHeight = (contentWidth / 592.28) * 841.89;// 未生成pdf的html页面高度let leftHeight = contentHeight;// 页面偏移let position = 0;// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高let imgWidth = 595.28;let imgHeight = (595.28 / contentWidth) * contentHeight;let pageData = canvas.toDataURL('image/jpeg', 1.0);let pdf = new JsPDF(null, 'pt', 'a4');// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)// 当内容未超过pdf一页显示的范围,无需分页if (leftHeight < pageHeight) {pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);} else {while (leftHeight > 0) {pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);leftHeight -= pageHeight;// 避免添加空白页position -= 841.89;if (leftHeight > 0) {pdf.addPage();}}}let nowDate = moment(new Date()).format('YYYY-MM-DD');if (isPrint) {//打印pdf.autoPrint();pdf.output('dataurlnewwindow');this.setState({ loading: false });} else {//下载pdf.save('发货单-' + nowDate + '.pdf');this.setState({ loadingDown: false });}});};const dataSource = [{key: '1',name: '胡彦斌',age: 1,ages: 2,agess: 3,agesss: 4,agesssx: 5,address: '个',sss: '是商品'},{key: '2',name: '胡彦祖',age: 7,ages: 8,agess: 9,agesss: 10,agesssx: 12,address: '组',sss: '不是商品'},{key: '2',name: '胡彦祖',age: 7,ages: 8,agess: 9,agesss: 10,agesssx: 12,address: '组',sss: '什么商品'}];return (<ModalmaskClosable={false}closable={false}title={null}width={1000}visible={this.state.deliverVisible}footer={null}><div className="deliverGoods" ref={pdfs as LegacyRef<HTMLDivElement>}><div className="deliverGoods_No">NO:1234567890</div><div className="deliverGoods_title"><h3>发货单</h3></div><div className="deliverGoods_count"><div><span>关联订单号:</span><span>123456789</span></div><div><span>下单时间:</span><span>2022-03-31 09:44:47</span></div></div><div className="deliverGoods_count"><div><span>收货信息:</span><span>奥利给,浙江杭州市上城区高德置地广场</span></div><div><span>发货时间:</span><span>2022-03-31 09:44:47</span></div></div><div className="deliverGoods_count"><div><span>下单客户:</span><span>测试客户</span></div><div><span>送货供应商:</span><span>XXX有限公司</span></div></div><div className="deliverGoods_table"><TablerowKey={(_record, index) => index.toString()}columns={this._columns}dataSource={dataSource}pagination={false}bordered/></div><div className="deliverGoods_No">商品金额:¥945.00</div><div className="deliverGoods_foot"><div><span>买家备注:</span><span>无</span></div><div><span>追加备注:</span><span>要红色的</span></div><div><span>客户签字:</span><span>奥利给</span></div><div><span>签收时间:</span><span>2022-03-31 09:44:47</span></div></div></div><divid="pdf-con"style={{backgroundColor: '#cccccc',opacity: 0}}></div><div className="foot">{/* 取消按钮关闭moadl */}<Button>取消</Button><Buttontype="primary"loading={this.state.loadingDown}onClick={() => {this.setState({ loadingDown: true });handlePrint(false);}}>下载</Button><Buttontype="primary"loading={this.state.loading}onClick={() => {this.setState({ loading: true });handlePrint(true);}}>打印</Button></div></Modal>);}
}

less样式

.deliverGoods {.deliverGoods_No {display: flex;justify-content: flex-end;}.deliverGoods_title {display: flex;justify-content: center;h3 {font-size: 30px;font-weight: bold;}}.deliverGoods_count {display: flex;justify-content: space-between;width: 80%;margin: 0 auto;line-height: 25px;}.deliverGoods_table {margin: 20px auto;}.deliverGoods_foot {display: flex;flex-direction: column;width: 80%;margin: 0 auto;line-height: 25px;}
}
.foot {display: flex;justify-content: space-evenly;width: 30%;margin: 0 auto;
}

如果所示:


打印单优化:(2022.06.30)

//打印单优化:优化打印像素和比例,更清晰(仅供参考)
//承接上边的代码
html2Canvas(cloneDom, {// scale: window.devicePixelRatio,scale: 2,allowTaint: true,useCORS: true,// 画布开始渲染的y坐标位置y: 0
}).then((canvas) => {let pdf = new JsPDF(null, 'pt', 'a4'); // A4纸,纵向var ctx = canvas.getContext('2d'),a4w = 560,a4h = 750, // A4大小,210mm x 297mm,保留左右20mm边距 上下30mm的边距,显示区域170x237imgHeight = Math.floor((a4h * canvas.width) / a4w), //按A4显示比例换算一页图像的像素高度renderedHeight = 0;while (renderedHeight < canvas.height) {var page = document.createElement('canvas');page.width = canvas.width;page.height = Math.min(imgHeight, canvas.height - renderedHeight); //可能内容不足一页//用getImageData剪裁指定区域,并画到前面创建的canvas对象中page.getContext('2d').putImageData(ctx.getImageData(0,renderedHeight,canvas.width,Math.min(imgHeight, canvas.height - renderedHeight)),0,0);pdf.addImage(page.toDataURL('image/jpeg', 1.0),'JPEG',20,30,a4w,Math.min(a4h, (a4w * page.height) / page.width)); // 添加图像到页面,保留左右20mm边距 上下30mmrenderedHeight += imgHeight;if (renderedHeight < canvas.height) pdf.addPage(); //如果后面还有内容,添加一个空页}// console.log('canvas', canvas);// let contentWidth = canvas.width;// let contentHeight = canvas.height;// // 一页pdf显示html页面生成的canvas高度;// let pageHeight = (contentWidth / 592.28) * 841.89;// // 未生成pdf的html页面高度// let leftHeight = contentHeight;// // 页面偏移// let position = 0;// // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高// let imgWidth = 595.28;// let imgHeight = (595.28 / contentWidth) * contentHeight;// let pageData = canvas.toDataURL('image/jpeg', 1.0);// let pdf = new JsPDF(null, 'pt', 'a4');// // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)// // 当内容未超过pdf一页显示的范围,无需分页// if (leftHeight < pageHeight) {//   pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);// } else {//   let i = 0;//   while (leftHeight > 0) {//     pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);//     leftHeight -= pageHeight;//     // 避免添加空白页//     position -= 841.89;//     if (leftHeight > 0) {//       pdf.addPage();//     }//   }// }let nowDate = moment(new Date()).format('YYYY-MM-DD');if (isPrint) {//打印pdf.autoPrint();pdf.output('dataurlnewwindow');this.setState({ loading: false });} else {//下载pdf.save('发货单-' + nowDate + '.pdf');this.setState({ loadingDown: false });}
});

工作是为了生活,但生活不是为了工作!

react引入html2canvas和jspdf生成PDF打印及下载相关推荐

  1. 前端使用html2canvas和jspdf生成pdf,以及清晰度问题

    前端使用html2canvas和jspdf生成pdf 参考文档:https://www.jianshu.com/p/56680ce1cc97 html2canvas 官网:http://html2ca ...

  2. html2Canvas+JsPDF生成pdf文件并下载

    采用html2Canvas+JsPDF实现web页面/dom元素转pdf文件并下载 1.安装html2Canvas: npm install html2canvas 2.安装JsPDF: npm in ...

  3. 【无标题】使用html2canvas和jspdf生成的pdf在不同大小的屏幕下文字大小不一样

    问题:使用html2canvas和jspdf生成的pdf在不同大小的屏幕下文字大小不一样,在mac下,一切正常,看起来很舒服,但是当我把页面放在扩展屏幕下(27寸),再生成一个pdf,虽然排版一样,但 ...

  4. 通过前端实现导出生成pdf文件并下载

    通过前端实现导出生成pdf文件并下载 使用 jspdf.js + html2canvas 插件,实现前端生成pdf 并下载的功能 步骤如下 1.先通过npm 安装插件 npm install jspd ...

  5. 前端实现生成pdf文件并下载

    前端实现生成pdf文件并下载 思路 下载依赖 使用方式 备注 参考 思路 通过 html2canvas 将 HTML 页面转换成图片,然后再通过 jspdf 将图片的 base64 生成为 pdf 文 ...

  6. 【生成PDF】Java如何根据前台Echarts图表生成PDF,并下载

    文章目录 前言 一.如何通过java代码生成PDF? 1.依赖 二.如何在PDF中画前台的echarts图? 1.如何拿到前台echarts图的信息? 前台代码: 后台逻辑:生成PDF,并下载 PDF ...

  7. jsPDF生成PDF文件,文件不全问题,后台进行文件下载,前台不下载

    我是前端使用jsPDF进行生成PDF文件,使用Base64进行加密,解密:后台进行文件流下载 1.前端使用jsPDF和html2canvas进行生成PDF文件(当然有这同样的毛病,生成时候有滚动条的情 ...

  8. jsPDF,生成pdf文件的助手

    jsPDF是一个强大的基于HTML5的PDF生成工具,许多公司需要用它来生成pdf报表. 我也是昨天才了解到它,所以我对于jspdf也是一知半解,在这里我归纳两种我觉得比较实用的生成方法. 链接地址h ...

  9. 前端vue项目,把某个div盒子或当前页面生成pdf文件并下载。

    安装依赖 1. npm install --save html2canvas // 作用是html转图片 2. npm install jspdf --save // 再将图片转为pdf 目录标题 安 ...

  10. java web pdf 打印预览_java原装代码完成pdf在线预览和pdf打印及下载

    前提准备: 1. 项目中至少需要引入的jar包,注意版本: a) core-renderer.jar b) freemarker-2.3.16.jar c) iText-2.0.8.jar d) iT ...

最新文章

  1. 你可能不知道的小程序
  2. c#冒泡、快速、选择和插入排序算法的项目应用
  3. Java 数字用二进制表示,以及原码,反码,补码、负数的二进制表示
  4. 按钮button的常用属性和事件
  5. 扬州工业机器人外壳设计排名_工业交换机的外壳设计重要吗?
  6. 线程间协作的两种方式:wait、notify、notifyAll和Condition
  7. Shell脚本基本规则
  8. 基于JAVA+SpringMVC+MYSQL的企业员工管理系统
  9. PyTorch Cookbook by Eric
  10. C++ coredump原因总结(转载)
  11. 华为s5720默认用户名和密码_华为交换机s5720s-28p-LI-AC默认用户名和密码是什么?...
  12. ankhsvn vs2017 64位下载 v2.7.12815
  13. Tensorflow nmt的整体结构
  14. Android 开发自己的网络收音机4——读取XML文件的电台数据
  15. Unity3D开发:向Unity3D中导入外部模型
  16. java中explain什么意思_explain详解
  17. 【云计算】一文了解裸金属服务器(一)
  18. Java泛型面试也能虐暴你
  19. glib实现Socket通信
  20. Excel中如何统计一行中指定类型元素的个数

热门文章

  1. 算法导论 9.1-1 “给出算法,在给定的比较次数(n+向上取整(lgn)-2)内,一定能找出第二小的元素。提示:也找出最小元素。”...
  2. 北京邮电大学计算机考研经验分享
  3. Mac上如何修改itunes的默认备份地址
  4. 聊一聊,android程序员前景如何
  5. 浏览器窗口通信的多种方式
  6. ImportError: cannot import name ‘export_saved_model‘ from ‘tensorflow.python.keras.saving.saved_mode
  7. 忘记MySQL密码如何重置再到重新设置密码
  8. Vlan和Trank
  9. ----uni-app之APP关联小程序实现扫描APP二维码跳转关联小程序----
  10. 转录组测序day 1 基础知识