本来今天准备继续更新webpack的内容的,但是上午修改了一下公司网站的代码,然后就开始研究网页打印的东西了,弄了一下午,搞的整个人都不好了。刚好也来讲一下一些收获,其实也不算什么收获,但是还是来跟大家分享一下。
window.print()
这个是实现网页打印的方法函数,其实针对网页打印,有几个应用场景;
- 第一种情况,最简单的应用,就是单纯的打印网页的文本内容,没有样式什么的特别需求。
- 第二种情况,就是根据项目要求,配合特定打印纸张的要求(例如A4纸、银行卡、质保卡、订单信息等),实现特定样式的打印
先来说一下,网站的打印方案有很多,但是讲到的都是第一种情况的打印实现,从我个人来说,作用不是很大,只是简单的介绍了怎样实现打印,但是我们的实际项目不可能说,单纯的把文本内容打印出来,既简单又丑陋。很多时候不论是客户还是公司来说,都希望你打印出来的东西跟你网页上,或者真实的打印单据的格式是一样的。
接下来我们开始讲我们的实现方案:
1、通常采用的是
iframe
打印方法,不管是实现局部,或者是实现整个页面的打印。当然,你的打印内容如果只是单纯页面上的内容,不需要通过数据交互获取数据之后再打印的除外。那我们先来将最简单的,就是你页面的单纯打印,这里分为
整体打印
和
局部打印。
不使用--iframe
整体打印-------直接调用方法就可以了
window.print();
局部打印-------打印的时候,把需要打印的内容替换成整个body内容(用户会在打印的时候看到变化,用户体验不太好)
<body> <!--startprint1--> <div id="printBody"> </div> <!--endprint1--> </body>JS
<script type="text/javascript"> var bdhtml; sprnstr; eprnstr; prnhtml; bdhtml=window.document.body.innerHTML;//获取当前页的html代码 sprnstr="<!--startprint1-->";//设置打印开始区域 eprnstr="<!--endprint1-->";//设置打印结束区域 prnhtml=bdhtml.substring(bdhtml.indexOf(sprnstr)+18); //从开始代码向后取html prnhtml=prnhtml.substring(0,prnhtml.indexOf(eprnstr));//从结束代码向前取html window.document.body.innerHTML=prnhtml; window.print(); </script>
使用--iframe
我非常不推荐上面的方法,他只是在你最简单的需求下才可以使用。说下为什么不推荐,上面的方法有几个坑,页面打印过后 会导致页面上所有的按钮,标签等绑定的事件都失效,这个你怕不怕;还有就是毕竟打印的是页面的一部分,看着不清楚也不 方便维护;而且如果是在页面上只有在需要的时候才调出来(例如事先隐藏起来,等到打印的时候再调用出来)有可能会导致 你整个页面样式的崩溃。
好了,转入正题,首先先要在所在的页面中放一个Iframe标签。记住宽和高都是0,这样不会对你的页面有丝毫的影响。
页面1(是需要调用到打印的页面)
<body style="text-align: center"> <button type="button" id="printBtn">打印</button> <iframe frameborder="0" src="" id="printFrame" style="width: 0;height: 0;"></iframe> <script type="text/javascript" src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> <script type="text/javascript"> $("#printBtn").click(function () { $("#printFrame").attr('src','./printIframe.html'); }) </script> </body>
页面2(printIframe.html页面)
<!DOCTYPE html> <html lang="en" style="height: 100%"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css" media="print"> html{ height: 100%; width: 100%; } </style> </head> <body style="padding: 0;margin: 0;height: 100%;width: 100%;"> <div id="printBody" style="width: 100%;height: 100%;"> </div> <script type="text/javascript" src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> <script type="text/javascript"> var pdata = [ {"id":"productId","top":"95","left":"20"}, {"id":"customer","top":"120","left":"80"}, {"id":"dfadfa","top":"150","left":"50"} ] var infoHtml = ''; for (var i = 0;i<pdata.length;i++){ var top1 = (pdata[i].top/176)*100+'%'; var left = (pdata[i].left/261)*100+'%'; infoHtml += '<span style="display:block;position:absolute;top:'+top1+';left:'+left+';">'+pdata[i].id+'</span>'; } $("#printBody").html(infoHtml); window.print(); </script> </body> </html>
讲一下,我的本次项目的要求是:
打印质保卡,类似于银行卡大小,上面带有背景图案,并且显示相应信息。
项目开始做了一下面的图片的页面(中间红色边框的背景图是先随意上传的,我们要实现的功能 就是和背景图一样的打印),复选框的选中与否代表着要显示在质保卡上的信息选项。然后出现 在红框内的选项字段是可以拖动的,拖动到确定位置之后,把信息保存下来作为将来打印的模 板。这部分保存的信息有(要显示的字段名称,其相对于红色框所在的位置,这里获取的是相对 于红色框的绝对定位位置,position为absolute的top和left值)。
下面的内容才是今天要讲到的主题,我们在printIframe.html中获取到数据(上面html中的pdata是假数据,跟真数据差不多),之前是直接拿到数据之后,在页面中按照绝对定位的px值进行定位,但是打印页面出来的想过不是预期的那样,我们想要的是上图红色框包含的样式。网页打印预览出来之后信息都出现在了左上角,并没有跟红色框所展现的那样进行布局。
这是因为,我们最初这是红色框的宽和高都是固定的为261px和176px,而打印网页是按照浏览器的window1大小的100%显示的,所以这里我们的打印页面的宽和高都是window的100%大小,所以我们这里的定位就不能直接用px只来定位了,应该用百分比来定位,之后这样才能让相应字段显示在相应位置。这里的一个核心思想就是,打印的布局样式要以打印窗口宽高的100%为基准来进行布局,通过计算出对应元素在页面中的百分比位置或者大小,才能够实现和局部样式一样的效果.