1.下载PDF
- 引入 html2canvas 和 jspdf
npm install html2canvas
npm install jspdf --save
2.在utils文件创建htmlToPdf.js
// 导出页面为PDF格式
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
install(Vue, options) {
Vue.prototype.getPdf = function(title) {
var element = document.querySelector('#pdfDom'); // 这个dom元素是要导出pdf的div容器
setTimeout(() => {
html2Canvas(element).then(function(canvas) {
var contentWidth = canvas.width;
var contentHeight = canvas.height;
// 一页pdf显示html页面生成的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
// 未生成pdf的html页面高度
var leftHeight = contentHeight;
// 页面偏移
var position = 0;
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
var imgWidth = 595.28;
var imgHeight = 592.28 / contentWidth * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var pdf = new JsPDF('', '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();
}
}
}
pdf.save(title + '.pdf');
});
}, 0);
}
}
}
3.mian.js 全局引用
import htmlToPdf from '@/utils/htmlToPdf'
Vue.use(htmlToPdf)
4.vue 文件使用
<template>
<div id="pdfDom">
<div class="title-right title-right">
<button @click="pfdBtn"
class="title-right-button no-print"
data-html2canvas-ignore="true"> 下载PDF </button>
<button data-html2canvas-ignore="true"
class="title-right-button no-print"
@click="pbgBtn"> 下载PNG </button>
<button data-html2canvas-ignore="true"
class="title-right-button no-print"
@click="printBtn"> 打印 </button>
</div>
</div>
</template>
methods: {
pfdBtn () {
window.scrollTo(0, 0);
this.getPdf(this.title);
},
}
2.导出png
- vue 文件(data-html2canvas-ignore=“true”)导出不显示
<template>
<section class="report"
ref="imageDom"
id="pdfDom">
<div class="report-container">
<div class="title">
<div class="title-middle">
</div>
<div class="title-right title-right">
<button @click="pfdBtn"
class="title-right-button no-print"
data-html2canvas-ignore="true"> 下载PDF </button>
<button data-html2canvas-ignore="true"
class="title-right-button no-print"
@click="pbgBtn"> 下载PNG </button>
<button data-html2canvas-ignore="true"
class="title-right-button no-print"
@click="printBtn"> 打印 </button>
</div>
</div>
<div class="user-info">
<div class="user-info-top">
<div class="user-info-top-left">
<div class="line-input">
<div class="line-input-title">报告:</div>
<input type="text"
class="line-input-input">
</div>
</div>
</div>
</div>
</div>
</section >
</template>
<script>
import html2canvas from 'html2canvas';
export default {
data () {
return {
}
},
methods: {
pbgBtn () {
html2canvas(this.$refs.imageDom, {
backgroundColor: '#ffffff'
}).then(canvas => {
var imgData = canvas.toDataURL("image/jpeg");
this.fileDownload(imgData);
})
},
fileDownload (downloadUrl, file) {
let aLink = document.createElement("a");
aLink.style.display = "none";
aLink.href = downloadUrl;
aLink.download = file;
// 触发点击-然后移除
document.body.appendChild(aLink);
aLink.click();
document.body.removeChild(aLink);
},
printBtn () {
this.$print(this.$refs.imageDom)
},
}
}
</script>
3.vue打印
1.首先在utils创建的print.js
// 打印类属性、方法定义
/* eslint-disable */
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!important;}</style>";
str += "<style>html,body,div{height: auto!important;margin:0;padding:0}</style>";
// str += "<style>html,body,div{height: auto!important;}</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 isNeedRemove = document.querySelectorAll('.isNeedRemove')
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++) {
console.log(isNeedRemove)
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++) {
if (isNeedRemove.length == 0) {
var imageURL = canvass[k4].toDataURL("image/png");
var img = document.createElement("img");
img.src = imageURL;
img.setAttribute('style', 'max-width: 100%;');
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);
}
}
//做分页
//style="page-break-after: always"
// var pages = document.querySelectorAll('.result');
// for (var k5 = 0; k5 < pages.length; k5++) {
// pages[k5].setAttribute('style', 'page-break-after: always');
// }
return this.dom.outerHTML;
},
writeIframe: function (content) {
var w, doc, iframe = document.createElement('iframe'),
f = document.body.appendChild(iframe);
iframe.id = "myIframe";
//iframe.style = "position:absolute;width:0;height:0;top:-10px;left:-10px;";
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();
var _this = this
iframe.onload = function () {
_this.toPrint(w);
setTimeout(function () {
document.body.removeChild(iframe)
}, 100)
}
},
toPrint: function (frameWindow) {
try {
setTimeout(function () {
frameWindow.focus();
try {
if (!frameWindow.document.execCommand('print', false, null)) {
frameWindow.print();
}
} catch (e) {
frameWindow.print();
}
frameWindow.close();
}, 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';
}
};
const MyPlugin = {}
MyPlugin.install = function (Vue, options) {
// 4. 添加实例方法
Vue.prototype.$print = Print
}
export default MyPlugin
- 在mian.js文件全局声明
import Print from '@/utils/print'
Vue.use(Print)
3.在vue 页面中不打印地方,使用class=“no-print”,如第2点vue文件显示