项目组最近有一个实现自定义页面尺寸打印的需求:
浏览了网上大部分的教程,基本总结如下:
使用 CSS 的 @page 规则:通过 @page 规则,可以定义打印页面的尺寸和边距。例如,可以使用 @page 规则来定义 A4 纸张的尺寸和边距,或者根据需要定义其他自定义尺寸的页面。
@page {
size: 210mm 297mm; /* A4 尺寸 */
/* 或者自定义页面尺寸 */
}
使用 JavaScript 来控制页面的打印参数,包括页面尺寸、边距等。可以通过 JavaScript 改变打印样式表中的参数,实现自定义页面尺寸的打印。
function setPrintStyles() {
const iframe = document.createElement('iframe');
//插入需要打印的目标元素
document.querySelector(‘body‘).appendChild(iframe)
//插入style
…………
}
使用打印预览对话框进行手动设置:在打印预览对话框中,用户可以手动选择页面尺寸、边距等打印参数,从而实现自定义页面尺寸的打印。
最终决定封装一个javascript文件来实现自定义页面尺寸打印。核心部分包括:
完整代码实现:
const defaultOptions = {
el: '', //打印目标dom节点
debug: true, //打开调试模式,会显示iframe,
importCss: true, //引入head 中的link stylesheet
importStyle: true, //引入style标签中的样式
loadCss: [], //需要载入的第三方样式表
title: '', //打印标题
delay: 300, //延迟打印时间,确保iframe中的静态资源加载完成
beforePrintHandle: null, //打开打印窗口前的钩子函数,可以针对打印文档进行自定义调整,接受一个document参数
afterPrintHandle: null, //打印完成的钩子函数
}
let iframe = null
let dom = null
const checkOptions = options => {
if(!options.el) {
throw new Error('el must be a nodeType')
}
return {
...defaultOptions,
...options
}
}
const printf = options => {
const op = checkOptions(options)
dom = op.el.cloneNode(true)
const handle = createIframe(op)
if(op.beforePrintHandle) {
op.beforePrintHandle(handle.contentDocument);
}
if (op.afterPrintHandle) {
op.afterPrintHandle();
}
setTimeout(() => {
handle.print();
if (op.debug === false) {
removeIframe();
}
}, op.delay)
}
const createIframe = (op) => {
const { debug, importCss, importStyle, loadCss, title} = op
removeIframe();
iframe = document.createElement('iframe');
if(debug === false) {
iframe.style.display = 'none'
}
//插入需要打印的目标元素
document.querySelector('body').appendChild(iframe)
iframe.contentDocument.title = title;
const { body, head } = iframe.contentDocument;
const contentWindow = iframe.contentWindow;
//插入head中的link stylesheet
if(importCss) {
const stylesheets = document.querySelectorAll("link[rel = 'stylesheet']")
stylesheets.forEach(item => {
head.appendChild(item.cloneNode(true))
})
}
//插入style
if (importStyle) {
const stylesheets = document.querySelectorAll("style")
stylesheets.forEach(item => {
body.appendChild(item.cloneNode(true))
})
}
//插入外部样式文件
if (Array.isArray(loadCss) && loadCss.length > 0) {
loadCss.forEach(item => {
head.appendChild(item)
})
}
body.appendChild(dom)
return contentWindow;
}
const removeIframe = () => {
if (iframe) {
document.querySelector('body').removeChild(iframe)
iframe = null
}
}
export default printf
在调用的时候这样使用即可:
// 打印事件处理
const printHandle = () => {
const style = document.createElement('style');
style.innerHTML = `@media print { @page {size:${宽}mm ${高}mm!important; margin: 0;padding: 0;} }`;
window.document.head.appendChild(style);
printf({
el: printRef.value, //打印目标dom节点
debug: false, //打开调试模式,会显示iframe,
importCss: true, //引入head 中的link stylesheet
importStyle: true, //引入style标签中的样式
delay: 300, //延迟打印时间,确保iframe中的静态资源加载完成
});
}