Vue使用printJS导出网页为pdf、printJS导出pdf

2024-01-09 08:52

本文主要是介绍Vue使用printJS导出网页为pdf、printJS导出pdf,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先放几个参考链接 感谢!

Vue使用PrintJS实现页面打印功能_vue print.js 设置打印pdf的大小-CSDN博客

前台导出pdf经验汇总 (html2canvas.js和浏览器自带的打印功能-print.js)以及后台一些导出pdf的方法_iqc后台管理系统怎么做到导出pdf-CSDN博客 vue 中使用print.js导出pdf_printjs导出文件命名-CSDN博客

解决使用printJS打印PDF时echarts图表无法打印的问题_print-js打印pdf出现params.printable.charat is not a fu-CSDN博客 printJs库的使用心得 printJs配置 echart table超出_print js 布局设置-CSDN博客

使用printJS打印PDF时cavans、echarts图表无法打印的问题 

当使用浏览器的打印功能window.print()无法打印网页上的canvas图像,但是可以通过转换canvas成一个图片的形式来实现canvas的打印。

解决方法
  • getElementById获取canvas元素。
  • 使用HTMLCanvasElement.toDataURL()的 toDataURL()方法获取canvas的base64码。
  • 将获取的base64动态添加到img标签的src上。(html里的img标签不要写src属性)
<img:src="canvasPrintpdfUrl"style="max-width: 80%; height: auto; display: block; margin: 0 auto"
/>
//canvass 转图片打印var canvass = document.getElementById("myCanvas");var imageURL = canvass.toDataURL("image/png");//获取canvas的base64码//给img的src赋值 _this.canvasPrintpdfUrl = imageURL;

解决使用printJS打印PDF时echarts图表无法打印的问题_print-js打印pdf出现params.printable.charat is not a fu-CSDN博客

截取视频vedio第一帧为图片再导出 ↓ 

js截取video视频某一帧做封面的简单案例_js中截取video作为封面-CSDN博客

需求:网页已经写成了pdf的样式,需要点击导出pdf按钮 调用浏览器系统预览-打印

2.安装

npm install print-js -save

3.引入 在想要引入的页面中添加如下代码

import printJS from 'print-js';

4.使用
在我们想打印内容的标签上添加id,如下

<div id="printContent">
...
...
</div>

简单使用例子

//添加页眉信息并打印图片
printJS({printable: 'images/print-01-highres.jpg', type: 'image', header: 'My cool image header'})//打印多张图片
printJS({printable: ['images/print-01-highres.jpg', 'images/print-02-highres.jpg', 'images/print-03-highres.jpg'],type: 'image', //有四种打印类型:'pdf'、'html'、'image'、'json'。header: 'Multiple Images',imageStyle: 'width:50%;margin-bottom:20px;'
})

配置 建议网上去查

本人项目使用、并适配项目需求仅限参考

问题一:网页需要导出为pdf,并且网页上涉及到 canvas和视频,但是printJs不能直接输出这两个就需要先转化为图片,

问题二:ignoreElements: ["no-print"]的使用 注意class="no-print" 才会生效!

问题三:网页上多图导出的时候 需要循环按比例缩小

  • 直接复制本人修改过的js源码,创建一个Print.js的文件,将下面代码复制进去

getStyle函数中可以写内联样式,覆盖外面原有的样式,以去除一些打印时不需要的而原HTML中有的样式

Print.js、unitChange.js 在最后

vue代码解析

<template>
<div><el-button       type="primary" plain @click="handleprint()">导出PDF</el-button>
<div id="pdfDom"><!-- class="no-print" 就不会打印元素包括该元素下的内容 --><div style="height: 72px" class="no-print">内容</div><div class="page-box">模拟的pdf的第一页</div><div class="page-box">模拟的pdf的第二页 内容包含视频需要转图片<!-- 视频截图需要加 no-print --><div :class="['info_pics_box1','no-print']"><video controls width="250" id="videoplayer"><source src="/media/cc0-videos/flower.webm" type="video/webm"></video></div><!-- 专门用来打印pdf的 用一个图↓ --><img:src="videoPrintUrl"style="max-width: 75%; height: auto; display: block; margin: 0 auto"v-if="videoPrintUrl"/>    </div><div class="page-box">模拟的pdf的第三页<div class="no-print"><canvas id="canvas"></canvas></div><!-- 专门用来打印pdf的 用一个图↓ --><img:src="canvasPrintpdfUrl"style="max-width: 80%; height: auto; display: block; margin: 0 auto"v-if="canvasPrintpdfUrl"/></div>
</div>
</div>
</template>
<script>
import Print from "@/utils/Print.js";
import unitChange from "@/utils/unitChange.js";
export default {
data() {return {pdfUrl: "",videoPrintUrl: "", //视频转图片打印isimgCut: true, //默认是图片截图 视频截图需要加 no-printcanvasPrintpdfUrl: "", //pdf canvas转打印图片}
}methods: {
//导出pdfhandleprint() {let _this = this;const filename = document.title + new Date().getTime();_this.setPrintStyle();_this.$nextTick(() => {Print("#pdfDom", {printable: "pdfDom", // 标签元素idtype: "pdf", // 打印类型// header: "", // '表单名称',targetStyles: ["*"],ignoreElements: ["no-print"], // class="no-print" 就不会打印该元素内容properties: null,documentTitle: filename,//貌似不生效paperSize: {height: "297mm", // 设置打印纸张的高度为 297mm(A4纸)},maxWidth: "100%",font_size: "24px",// 可选-打印时去掉眉页眉尾↓style: `@page{margin:0 10mm;}@media print{html,body{width:1920px;height:100%;margin:0;}}`,afterprint: () => {console.log("打印了");_this.restoredata();//打印后还原页面样式},cancel: () => {console.log("取消打印");_this.restoredata();//打印后还原页面样式},});});},setPrintStyle() {let _this = this;// if (_this.zoomStatus) return;// _this.zoomStatus = true;// 保证打印正好铺满A4高度let A4height = 297; // A4高度297mmlet ctxpage = document.querySelectorAll(".page-box");ctxpage.forEach((i, k) => {let eachpage_mm = unitChange.px2mm(i.clientHeight); // 单位px转mmconsole.log(k + "页高度px:", i.clientHeight, "高度mm:", eachpage_mm);//高度大于A4,则按比例缩小打印区域if (eachpage_mm > A4height) {let zoom = A4height / eachpage_mm;console.log(k + "页zoom:", zoom);i.style.zoom = 1;}});//图片缩小let photos = document.querySelectorAll("#pointers"); //获取页面上的图片id 可以换imgif (photos.length > 0) {photos.forEach((i, k) => {//高度大于A4,则按比例缩小打印区域// i.style.zoom = 0.6;i.style.width = "60%";i.style.display = "block";i.style.margin = "auto";//打印图片居中});}//视频转图片打印_this.$nextTick(() => {let videoplayers = document.querySelector("#videoplayer");if (videoplayers) {var theprintcanvas = document.createElement("canvas"); //创建cavansvar context = theprintcanvas.getContext("2d"); // 获取2D绘图上下文theprintcanvas.width = videoplayers.clientWidth;theprintcanvas.height = videoplayers.clientHeight;// 绘制视频第一帧到画布上context.drawImage(videoplayers, 0, 0);const dataURL = theprintcanvas.toDataURL("image/png");_this.videoPrintUrl = dataURL;} else {console.error("无法找到视频元素或画布元素!");}});//canvass转图片打印let canvass = document.querySelectorAll("canvas");for (var k4 = 0; k4 < canvass.length; k4++) {var imageURL = canvass[k4].toDataURL("image/png");_this.canvasPrintpdfUrl = imageURL;}},//打印后还原页面样式restoredata() {//打印后还原某些元素this.videoPrintUrl = ""; //视频的this.canvasPrintpdfUrl = ""; //pdf canvas转打印图片let ctxpage = document.querySelectorAll(".page-box");ctxpage.forEach((i, k) => {let eachpage_mm = unitChange.px2mm(i.clientHeight); // 单位px转mmi.style.zoom = 1;});let photos = document.querySelectorAll("#pointers");photos.forEach((i, k) => {i.style.width = "100%";});},}
}
</script><style>::-webkit-scrollbar {width: 0 !important;
}
::-webkit-scrollbar {width: 0 !important;height: 0;
}
body::-webkit-scrollbar {display: none;
}
body {-ms-overflow-style: none;
}
html {overflow: -moz-hidden-unscrollable; /*注意!若只打 hidden,chrome 的其它 hidden 会出问题*/height: 100%;
}
/*不打印页脚的链接  --放在样式中*/
@page {margin-top: 1mm;margin-bottom: 1mm;padding-top: 1mm;
}
/*隐藏打印页面不需要的按钮*/
@media print {.btn{display: none;}}
</style>

两个js文件引入:

Print.js

/***** iframe打印* @param dom            打印区域的class, id* @param options.margin  控制页眉页脚, 默认 4mm* @param options.padding 打印边距, 默认 '0 0'* @method options.afterprint 打印结束后回调* @method options.cancel 取消打印后回调** **/const Print = function (dom, options) {if (!(this instanceof Print)) return new Print(dom, options);this.options = this.extend({noPrint: ".no-print",},options);if (typeof dom === "string") {this.dom = document.querySelector(dom);} else {this.isDOM(dom);this.dom = this.isDOM(dom) ? dom : dom.$el;}this.init();
};
Print.prototype = {init: function () {var content = this.getStyle() + this.getHtml();this.writeIframe(content);},extend: function (obj, obj2) {for (var k in obj2) {obj[k] = obj2[k];}return obj;},getStyle: function () {var str = "",styles = document.querySelectorAll("style,link");for (var i = 0; i < styles.length; i++) {str += styles[i].outerHTML;}str +="<style>" +(this.options.noPrint ? this.options.noPrint : ".no-print") +"{display:none;}</style>";str += `<style>@media print { @page { margin: ${this.options.margin || "4mm"}; padding: ${this.options.padding || "0 0"}; width:210mm;height:290mm} body {  -webkit-print-color-adjust:exact;-moz-print-color-adjust:exact;-ms-print-color-adjust:exact;print-color-adjust:exact; } }</style>`;return str;},getHtml: function () {var inputs = document.querySelectorAll("input");var textareas = document.querySelectorAll("textarea");var selects = document.querySelectorAll("select");var canvass = document.querySelectorAll("canvas");var tableNode = document.querySelectorAll(".el-table__header,.el-table__body");for (var k = 0; k < inputs.length; k++) {if (inputs[k].type == "checkbox" || inputs[k].type == "radio") {if (inputs[k].checked == true) {inputs[k].setAttribute("checked", "checked");} else {inputs[k].removeAttribute("checked");}} else if (inputs[k].type == "text") {inputs[k].setAttribute("value", inputs[k].value);} else {inputs[k].setAttribute("value", inputs[k].value);}}for (var k2 = 0; k2 < textareas.length; k2++) {if (textareas[k2].type == "textarea") {textareas[k2].innerHTML = textareas[k2].value;}}for (var k3 = 0; k3 < selects.length; k3++) {if (selects[k3].type == "select-one") {var child = selects[k3].children;for (var i in child) {if (child[i].tagName == "OPTION") {if (child[i].selected == true) {child[i].setAttribute("selected", "selected");} else {child[i].removeAttribute("selected");}}}}}// canvass echars图表转为图片for (var k4 = 0; k4 < canvass.length; k4++) {var imageURL = canvass[k4].toDataURL("image/png");// console.log('imageURL',imageURL)var img = document.createElement("img");img.src = imageURL;img.setAttribute("style", "max-width: 80%;height:auto");img.className = "isNeedRemove";// canvass[k4].style.display = 'none'// canvass[k4].parentNode.style.width = '100%'// canvass[k4].parentNode.style.textAlign = 'center'canvass[k4].parentNode.insertBefore(img, canvass[k4].nextElementSibling);}// console.log(tableNode);//el-table 打印预览的时候,宽度占满// for (let k6 = 0; k6 < tableNode.length; k6++) {//   const tableItem = tableNode[k6];//   tableItem.style.width = "100%";// }return this.dom.outerHTML;},writeIframe: function (content) {var w,doc,iframe = document.createElement("iframe"),f = document.body.appendChild(iframe);iframe.id = "myIframe";iframe.setAttribute("style","position:absolute;width:0;height:0;top:-10px;left:-10px;");w = f.contentWindow || f.contentDocument;doc = f.contentDocument || f.contentWindow.document;doc.open();doc.write(content);doc.close();// 避免重复打印 canvas、echartsvar removes = document.querySelectorAll('.isNeedRemove');for (var k = 0; k < removes.length; k++) {removes[k].parentNode.removeChild(removes[k]);}var _this = this;iframe.onload = function () {w.onbeforeprint = _this.options.beforeprint;w.onafterprint = _this.options.afterprint;// iframe.contentWindow.print();_this.toPrint(w);setTimeout(function () {document.body.removeChild(iframe);}, 100);};},toPrint: function (frameWindow) {var _t = this;try {setTimeout(function () {frameWindow.focus();try {if (!frameWindow.document.execCommand("print", false, null)) {frameWindow.print();}} catch (e) {frameWindow.print();}frameWindow.close();typeof _t.options.cancel === "function" && _t.options.cancel();frameWindow.onbeforeprint = null;frameWindow.onafterprint = null;}, 10);} catch (err) {console.log("err", err);}},isDOM:typeof HTMLElement === "object"? function (obj) {return obj instanceof HTMLElement;}: function (obj) {return (obj &&typeof obj === "object" &&obj.nodeType === 1 &&typeof obj.nodeName === "string");},
};
// 原生JS使用此JS文件实现打印,请删除下边的代码
// const MyPlugin = {};
// MyPlugin.install = function (Vue, options) {
//   // 4. 添加实例方法
//   Vue.prototype.$print = Print;
// };
export default Print;

unitChange.js

//  px <-> mm  单位互相转换/*** 获取DPI 每英寸像素点* @returns {Array}*/
let conversion_getDPI = function() {var DPI = 0;if (window.screen.deviceXDPI) {DPI = window.screen.deviceXDPI;} else {var tmpNode = document.createElement("DIV");tmpNode.style.cssText ="width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";document.body.appendChild(tmpNode);DPI = parseInt(tmpNode.offsetWidth); tmpNode.parentNode.removeChild(tmpNode);} return DPI;};// 1 英寸=25.4 毫米/*** px转换为mm* @param value* @returns {number}*/let px2mm = function(value) {var inch = value / conversion_getDPI();var c_value = inch * 25.4;//      console.log(c_value);return c_value;};/*** mm转换为px* @param value* @returns {number}*/let mm2px = function(value) {var inch = value / 25.4;var c_value = inch * conversion_getDPI();//      console.log(c_value);return c_value;};export default {mm2px,px2mm};

这篇关于Vue使用printJS导出网页为pdf、printJS导出pdf的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/586570

相关文章

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

在React中引入Tailwind CSS的完整指南

《在React中引入TailwindCSS的完整指南》在现代前端开发中,使用UI库可以显著提高开发效率,TailwindCSS是一个功能类优先的CSS框架,本文将详细介绍如何在Reac... 目录前言一、Tailwind css 简介二、创建 React 项目使用 Create React App 创建项目

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain