前言
需要使用html实现打印前预览的界面,要求预览结果与打印效果相同
使用环境: bootstrapVue
文章目录
- 前言
- 一、A4模板效果
- 二、制作A4模板
- 1.思考界面结构(以所附demo[A4.html]分析)
- 2. 限制页面大小
- 三、预览功能
- 四、实现打印
- 五、 实现效果
- 总结
一、A4模板效果
附实现效果(demo)
应用流程为点击界面的预览按钮,弹出窗口为制作的A4界面。
二、制作A4模板
1.思考界面结构(以所附demo[A4.html]分析)
- 模板分为头部,中间内容,底部footer三块内容(除去大标题),使用flex布局实现整个界面,因为中间的内容是不固定的,所以让它占据空间的最大内容,使用
flex-grow:1
占据空间,从而使布局分为上中下三块。
代码结构如下(示例):<!--代码实例中的css定义直接用的bootstrap的公共样式方便代码编写,观看直接,实际html不能直接用类名的,需要另外编写css--> <div class="root d-flex flex-column"> <div class="header"></div> <div class="content flex-grow-1"></div> <div class="footer"></div> </div>
2. 限制页面大小
- 需要将页面的大小限制在A4大小,因为用于打印,所以单位使用了mm,A4大小的宽高为(210mm,297mm)
/*这是将打印时的页面大小设置为A4大小,并保留好一定的边距*/ @page { /* size: 21cm 29.7cm; */ font-size: 14pt; font-family: SimSun, 宋体, serif; color:black; line-height: 1.4; text-align: justify; margin:0; padding:0; }
body{ font-size: 14pt; /*在打印中,字体大小使用pt单位*/ font-family: "Times New Roman", Times, serif; } .root{ /*需要将预览显示的界面限定在A4大小*/ width:210mm; /*这个高度为什么不是A4的大小,是经过N次验证的方式得到的,唯一的目的就是为了保证预览和打印预览一致*/ /*可能是我写的有一点问题,但是如果设置为297,那么显示就会出现问题*/ height:340mm; /*上下不要设置padding,否则打印预览下面的footer就会往上走*/ padding: 0 24mm 0 24mm; /* margin-bottom: 24mm; */ background-color: white; } /*下面两个样式是为了保证屏幕上预览和打印预览一致*/ @media screen{ .content{ width:210mm; height:340mm; /* padding-top:12mm; */ display: flex; flex-direction: column; } } @media print{ .content{ width:210mm; height:340mm; padding-top:18mm; display: flex; flex-direction: column; } }
- 之后通过flex布局模式将内容排好版之后可使用浏览器打印功能预览打印结果,如果有打印部分有与html结构不同的地方,可能是因为浏览器的打印预设,可使用下面的方法自己设定样式
/*第一种*/ @media print{ /*这个方法用在需要编写的样式不是太多的情况下*/ .root{ /*这里面写需要的样式,这里的样式只在打印时才会用到*/ } } /*第二种*/ /*可单独编写一个文件专门用于打印的样式,如果需要编写的样式很多的情况下*/ 1. 新建print.css 2. 引入文件 <link rel="stylesheet" href="../src/css/screen.css" media="screen"> <link rel="stylesheet" href="../src/css/print.css" media="print">
三、预览功能
点击预览 --> 弹出界面(界面居中),模板大小随着屏幕自适应,全部出现在界面上而不滚动 --> 点击下面的按钮关闭预览
-
设置iframe,嵌入写好的模板
代码结构如下(show.vue):
html部分 <!--通过变量值判断应该用什么样式--> <div :class="{ 'template-wrapper-show': isTemplateShow, 'template-wrapper-hidden': !isTemplateShow }" class="text-center" id="template-wrapper" > <div class="d-flex flex-column justify-content-center align-items-center w-100 h-100" > <div id="iframe-wrapper" :style="iframeSize"> <iframe src="./A4.html" frameborder="0" id="iframeId" :style="iframeStyle" name="iframeId" scrolling="no" class="iframe-content" > <p>您的浏览器不支持 iframe 标签。</p> </iframe> </div> <!--关闭按钮--> <div class=""> <b-button variant="outline" size="lg" @click=" () => { this.isTemplateShow = false; } " > <b-icon icon="x-circle" variant="white"></b-icon> </b-button> </div> </div> </div>
通过样式变化来确定是否显示iframe(原本打算将iframe放在modal中,以此来控制显示,但是modal获取不到iframe的宽高,所以在控制高度方面不是很方便,因此使用原生的样式来写),控制的css如下:
.template-wrapper-hidden { /*设置absolute使得 visibility:hidden时不占据空间*/ /* position: absolute; */ /* visibility: hidden; */ overflow: hidden; display: none; /*到最后发现还是这个最好使*/ } .template-wrapper-show { /*设置一个遮罩层,占满屏幕*/ position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.3); /*让遮罩层位于屏幕的最上方*/ z-index: 1000; } .iframe-content { /*只为了能完全显示那个html界面*/ width: 260mm; height: 360mm; transform-origin: left top; overflow: hidden; }
-
实现缩放(实现难点)
- 在页面加载的时候,需要获取到屏幕的大小,从而按比例缩小模板大小以整个显示在屏幕上
- 为了实现打印,模板的单位使用的是mm单位,而屏幕显示使用的是px单位,因此在计算时需要转换单位,计算的比例才有效
- 最后决定缩放的大小需要进行判断,因为要适配各个屏幕的大小。
- 实现
// 1. 获取屏幕大小,在页面加载时调用获取屏幕的方法 //获取DPI js_getDPI() { var arrDPI = new Array(); if (window.screen.deviceXDPI != undefined) { arrDPI[0] = window.screen.deviceXDPI; arrDPI[1] = window.screen.deviceYDPI; } 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); arrDPI[0] = parseInt(tmpNode.offsetWidth); arrDPI[1] = parseInt(tmpNode.offsetHeight); tmpNode.parentNode.removeChild(tmpNode); } return arrDPI; }, //方法来源于网络,用的现成的
// 2. 转换单位 js_convertMm() { const dpiArray = this.js_getDPI(); let templateArray = []; //转换的原理可以百度一下, 260和360是设置的div宽高 let px = (260 * dpiArray[0]) / 25.4; let py = (360 * dpiArray[1]) / 25.4; templateArray[0] = px; templateArray[1] = py; return templateArray; },
// 3. 计算缩放比 populateIframeScale() { const winWidth = window.innerWidth - 50; const winHeight = window.innerHeight - 50; let templateSize = this.js_convertMm(); const widthScale = Number((winWidth / templateSize[0]).toFixed(2)); const heightScale = Number((winHeight / templateSize[1]).toFixed(2)); if ( (widthScale <= 0.85 || heightScale <= 0.85) && widthScale <= heightScale ) { return widthScale; } else if ( (widthScale <= 0.85 || heightScale <= 0.85) && widthScale > heightScale ) { return heightScale; //如果计算得到的比例大于0.85,则按0.85的缩放比显示,因为预览的下面还有关闭按钮,需要预留一定的空间 } else if (widthScale > 0.85 && heightScale > 0.85) { return 0.85; } return 1; }, //使用计算属性将计算出的缩放比例运用到iframe的样式上 conputed(){ iframeStyle() { let scale = this.populateIframeScale(); return { transform: "scale(" + scale + ")" }; } }
四、实现打印
- 实现打印就比较简单,使用js的方法就可以,记录一下
printTemplate() { //第一种打印; // let f = document.getElementById("iframeId"); // f.contentWindow.focus(); // f.contentWindow.print(); //第二种打印; window.frames["iframeId"].focus(); window.frames["iframeId"].print(); },
五、 实现效果
- 大屏显示预览
- 中屏显示效果
- 手机显示
- 横屏
总结
- 记录了印象比较深的一些步骤点,可能有还有一些琐碎的点没有记录,如果有想到再来补充。
- 为保证预览和打印预览一致,对于高度的调节是比较麻烦的,如果设置的不好,则底下的footer后就会有一大段留白。
更多推荐
HTML实现A4模板
发布评论