网站建设 人性的弱点,做网站公司报价,河南自助建站建设代理,企业服务专员一文弄懂window.print 打印前言window.print() 默认效果缺陷一、打印样式二、打印指定区域内容1. 对容器进行打印2. 对容器内的部分内容进行打印3. 监听打印前后事件4. iframe三、强行插入分页四、打印设置五、最佳实践#xff08;React#xff09;1. 背景#xff1a;2. 思路…
一文弄懂window.print 打印前言window.print() 默认效果缺陷一、打印样式二、打印指定区域内容1. 对容器进行打印2. 对容器内的部分内容进行打印3. 监听打印前后事件4. iframe三、强行插入分页四、打印设置五、最佳实践React1. 背景2. 思路3. 实现六、如果干预打印分页七、 window.print去除浏览器默认页眉页脚window.print() 实现A4纸张打印及去掉页眉页脚及打印链接window.print() 去掉页眉页脚及打印链接八 、IE浏览器打印预览 使用html 标签object引入Webbrowser控件https://developer.mozilla.org/en-US/docs/Web/API/Window/print
前言
一般信息填写类的需求页面都会增设「预览」和「打印」功能。我们会通过编写 DOM 及样式来绘制出预览视图而打印则是基于预览来生成 PDF 文件。
浏览器原生 API window.print() 可以用于打印当前窗口window.document视图内容。调用此方法会产生一个打印预览弹框用户可以根据具体设置来得到打印结果。
window.print() 默认效果缺陷
1.打印控件默认没给分页就只显示了一页
2.dom 布局和样式很容易发生错位、丢失
3.我想要局部打印但默认是获取的整个 body.innerHtml 的内容
一、打印样式
默认情况下基于页面上的内容会将元素布局和样式都进行打印
如果仅想在打印上设置特殊样式可以通过以下方式 1.使用打印样式表
link hrefprint.css mediaprint relstylesheet / 2.使用媒介查询
media print {p{color: lavender;background: #ccc;}h1{color: lightblue;background: #ccc;}
} 3.使用内联 media 属性
style mediaprint p{color: lavender;background: #ccc;}h1{color: lightblue;background: #ccc;} /style 默认情况下元素的背景色不会被打印可通过设置属性来支持
div{// Chrome、Safari 等 webkit 浏览器内核-webkit-print-color-adjust: exact;// 火狐print-color-adjust: exact;color-adjust: exact;
} 二、打印指定区域内容
默认情况下调用 window.print() 会对整个 document.body 进行打印当需要打印指定容器内容时可以通过以下几种方式
1. 对容器进行打印
bodydiv idcontainerp这是一个段落/ph1这是一个标题/h1/divinput typebutton value打印此页面 onclickprintpage() /
script const printpage () {let newstr document.getElementById(container).innerHTML;let oldstr document.body.innerHTML;document.body.innerHTML newstr;window.print();document.body.innerHTML oldstr;}
/script
/body 2. 对容器内的部分内容进行打印
当只需要打印容器内某一部分内容时可以通过注释标识进行截取。
bodydiv idcontainer!--startprint--p这是一个段落/p!--endprint--h1这是一个标题/h1/divinput typebutton value打印此页面 onclickprintpage() /script const printpage () {let oldStr window.document.body.innerHTML; // 获取body的内容let start !--startprint--; // 开始打印标识, 17个字符let end !--endprint--; // 结束打印标识let newStr oldStr.substr(oldStr.indexOf(start) 17); // 截取开始打印标识之后的内容newStr newStr.substring(0, newStr.indexOf(end)); // 截取开始打印标识和结束打印标识之间的内容window.document.body.innerHTML newStr; // 把需要打印的指定内容赋给bodywindow.print(); // 调用浏览器的打印功能打印指定区域window.document.body.innerHTML oldStr; // body替换为原来的内容} /script
/body 3. 监听打印前后事件
通过监听打印前后事件window.onbeforeprint、window.onafterprint 对不需要进行打印的元素进行隐藏和放开隐藏。
body
div idcontainer
p这是一个段落/ph1 idtitle这是一个标题/h1
/div
input typebutton value打印此页面 onclickprintpage() /
script
const printpage () {window.print();}
window.onbeforeprint function() {
// 将一些不需要被打印的元素隐藏
document.getElementById(title).style.display none;}
window.onafterprint function() {
// 放开隐藏的元素
document.getElementById(title).style.display block;
}
/script
/body 4. iframe
上面几种方式都在当前窗口进行打印并且都需要更改 document.body 内容这会出现视图切换带来的体验不是太好。
下面我们借助 iframe 来实现打印并且不影响当前视窗的内容展示。
bodydiv idcontainerp这是一个段落/ph1 idtitle这是一个标题/h1/divinput typebutton value打印此页面 onclickprintpage() /scriptconst printpage () {const printContent document.querySelector(#container).innerHTML;const iframe document.createElement(iframe);iframe.setAttribute(style, position: absolute; width: 0; height: 0;);document.body.appendChild(iframe);const iframeDoc iframe.contentWindow.document;// 设置打印展示方式 - 横向展示iframeDoc.write(style mediaprintpage {size: landscape;}/style);// 向 iframe 中注入 printContent 样式iframeDoc.write(link href./print.css mediaprint relstylesheet /);// 写入内容iframeDoc.write(div printContent /div);setTimeout(function(){iframe.contentWindow.print();document.body.removeChild(iframe);}, 50);}/script
/body三、强行插入分页
当需要自定义打印分页时机时可通过如下方式将指定 DOM 设为分割点。
1.在指定元素前添加分页符
media print {h1 {page-break-before: always;}
} 2.在指定元素后添加分页符
media print {h1 {page-break-after: always;}
} 四、打印设置
1.设置打印布局
media print {page {/* 纵向展示高度展示内容更多 *//* size: portrait;*//* 横向宽度展示内容更大 */size: landscape;/* 打印的边距 上右下左 */margin: 1cm 2cm 1cm 2cm;}
} 注意一旦设置为 size: landscape在打印时将不能切换展示模式包括纸张类的设置。
五、最佳实践React
1. 背景
有一个信息填写页面支持进行预览和打印预览是一个 Dialog 弹框打印取自于预览的内容。因此在打印前需要将预览内容呈现在 DOM 树上。
2. 思路
点击打印将预览 Dialog open state 设置为 trueDialog 渲染到 DOM 树上执行 setTimeout 延迟任务在 Dialog 渲染在 DOM 树上后对其隐藏disabled: none目的是实现视图上不展示 Dialog创建 iframe并将 Dialog 内容及其样式写入 iframe.document 中执行 iframe.contentWindow.print() 进行打印打印完成后做一些重置处理移除 iframe、将 Dialog 隐藏逻辑去掉、将 Dialog open state 置为 false 这样在不影响现有页面内容的展示同时实现了打印 Dialog 内容。
3. 实现
const printFocus () {
// 打印事件// 1.挂载要打印的内容setPreviewOpen(true);setTimeout(() { // 延迟等待 Dialog 渲染在 DOM 树上// 2.隐藏要打印的内容const container document.querySelector(.preview-wrapper);container.setAttribute(style,display: none;);// 3. 创建 iframeconst iframe document.createElement(iframe);const printContent container.innerHTML;iframe.setAttribute(style, position: absolute; width: 0;height: 0;);document.body.appendChild(iframe);const doc iframe.contentWindow.document;// 4. 写入内容// doc.write(style mediaprint page {size: landscape;}/style);doc.write(link href./preview-focus.css mediaprint relstylesheet /);doc.write(div printContent /div);const link doc.getElementsByTagName(link)[0];link.onload () { // 样式文件加载完毕后打印// 5.执行打印iframe.contentWindow.print();// 6.重置工作document.body.removeChild(iframe);setPreviewOpen(false);container.removeAttribute(style);}},0);
}六、如果干预打印分页
通常我们会遇到这种情况在打印内容多于一页时会自动进行分页若分页的分割点恰巧是一行文字就会出现文字被切割分别显示在上下两页。
尽管我们可以通过 CSS 属性 page-break-before: always; 来干预分页但页面内容并非固定的如何将这个属性恰巧应用在分割点的 DOM 元素之上呢
下面有一个思路可以参考一下
1.为可能会被分割的元素设置自定义属性用于查找访问 2.根据打印视窗的每页高度粗估一个高度值作为页面分割的参考 3.遍历可分割元素判断它们是否处于页面分割位置top pageHeight botton pageHeight 4.若处于页面分割位置为此 DOM 设置分割属性 page-break-before: always;。 代码实现
!-- 自定义属性标识 --
div key{index} data-identpage-break classNamemodule-paragraphscript
// 1、获取可能会被分页符分割的元素c
onst pageBreakEles container.querySelectorAll([data-ident page-break]) || [];
// 2、定义打印页面的高度假设粗估后为 877px
const printPageHeight 877;
// 3、匹配元素是否处于页面分割线位置
Array.from(pageBreakEles).forEach(ele {const { top, bottom } ele.getBoundingClientRect();
// 根据高度计算元素处于第几页
const currentPage Math.floor(top / printPageHeight);
// 处于分页符位置的元素设置分割属性
if ((top - currentPage * printPageHeight) printPageHeight (bottom - currentPage * printPageHeight) printPageHeight) {(ele as HTMLElement).style.setProperty(page-break-before, always);
}});
/script 七、 window.print去除浏览器默认页眉页脚
打印时默认有页眉页脚信息显示在页面外边距范围我们可以通过去除页面模型page的外边距使其隐藏页眉页脚信息再通过设置 body 元素的 margin 来保证打印出来的页面带有外边距
media print {page {margin: 0;}body {margin: 1cm;}
}//打印(兼容IE浏览器)function webPrint(objId){var printContentdocument.getElementById(objId).innerHTML;//获得需要打印内容的HTML代码PageSetup_Null();//把页眉页脚设置为空printWindowwindow.open(,_blank);printWindow.document.write(!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtdhtml xmlnshttp://www.w3.org/1999/xhtmlheadmeta http-equivContent-Type contenttext/html; charsetutf-8 / title/titlestylepage{margin-bottom:0mm;margin-top:2mm}/style/headbody);//这里是向新建的窗口写入HTML的head信息可引入自己的js和css以供打印时样式与网页中显示的一致printWindow.document.write(div stylewidth:100%; height:100%;printContent/div);//这里向新建的窗体中写入BODY的内容注意外边加的额外DIV是有必要的它里面CSS可以控制打印时不会出现空白页printWindow.document.write(/body/html);//这里向新建的窗体写入HTML的结束标记printWindow.document.close();//关闭新建窗口的文档输出流否则下面的打印语句无效printWindow.print();//打印当前新建窗口中的内容printWindow.close();//关闭新建的窗口PageSetup_Default();//把页眉页脚恢复为默认}//设置网页打印的页眉页脚为空function PageSetup_Null(){var HKEY_Root,HKEY_Path,HKEY_Key;HKEY_RootHKEY_CURRENT_USER;HKEY_Path\\Software\\Microsoft\\Internet Explorer\\PageSetup\\;try{var Wshnew ActiveXObject(WScript.Shell);HKEY_Keyheader;Wsh.RegWrite(HKEY_RootHKEY_PathHKEY_Key,);HKEY_Keyfooter;Wsh.RegWrite(HKEY_RootHKEY_PathHKEY_Key,);}catch(e){}}//设置网页打印的页眉页脚为默认值function PageSetup_Default(){var HKEY_Root,HKEY_Path,HKEY_Key;HKEY_RootHKEY_CURRENT_USER;HKEY_Path\\Software\\Microsoft\\Internet Explorer\\PageSetup\\;try{var Wshnew ActiveXObject(WScript.Shell);HKEY_Keyheader;Wsh.RegWrite(HKEY_RootHKEY_PathHKEY_Key,wb页码p/P);HKEY_Keyfooter;Wsh.RegWrite(HKEY_RootHKEY_PathHKEY_Key,ubd);}catch(e){}}window.print() 实现A4纸张打印及去掉页眉页脚及打印链接
!DOCTYPE html
html langzh-CNheadmeta charsetutf-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1!-- 上述3个meta标签*必须*放在最前面任何其他内容都*必须*跟随其后 --title测评表/title!-- Bootstrap --link hrefhttps://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css relstylesheet!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --!-- WARNING: Respond.js doesnt work if you view the page via file:// --!--[if lt IE 9]script srchttps://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js/scriptscript srchttps://cdn.bootcss.com/respond.js/1.4.2/respond.min.js/script![endif]--/headstyle.a4-endwise{width: 1075px;height: 1400px;border: 1px #000 solid;overflow: hidden;padding: 0;word-break:break-all;text-align:center;}.a4-endwise table{border: 1px #000 solid;width: 80%;max-width: 80%;margin: 0px 100px;text-align: center;font-size: 20px;}.print{position: fixed;top: 1%;right: 10%;}/stylebody
a classprint hrefjavascript:; onclickpreview();打印/a
!--startprint--div classcontainer a4-endwise idtest/div
!--endprint--!-- jQuery (necessary for Bootstraps JavaScript plugins) --script srchttps://cdn.bootcss.com/jquery/1.12.4/jquery.min.js/script!-- Include all compiled plugins (below), or include individual files as needed --script srchttps://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js/scriptscript/*** [打印]* return {[type]} [description]*/function preview(){bdhtmlwindow.document.body.innerHTML;//获取当前页的html代码sprnstr!--startprint--;//设置打印开始区域eprnstr!--endprint--;//设置打印结束区域prnhtmlbdhtml.substring(bdhtml.indexOf(sprnstr)18); //从开始代码向后取htmlprnhtmlprnhtml.substring(0,prnhtml.indexOf(eprnstr));//从结束代码向前取htmlwindow.document.body.innerHTMLprnhtml;window.print();window.document.body.innerHTMLbdhtml;}/script/body
/htmlwindow.print() 去掉页眉页脚及打印链接 style mediaprintpage {size: auto; /* auto is the initial value */margin: 0mm; /* this affects the margin in the printer settings */}
/style八 、IE浏览器打印预览 使用html 标签引入Webbrowser控件
最近遇到这么一个需求需要在IE浏览器上打印的时候不直接调用打印机而是先打开打印预览页面再进行打印操作。 这样就需要对原本的打印方法进行改写了。使用html 标签object引入Webbrowser控件这种方式优势是在IE下可以弹出打印预览这是打印很人性化的功能但是遗憾的是高版本的IE浏览器不支持WebBrowser了。 具体实现如下
!-- 在body标签中写入一个object --
object idprintWB styledispaly:none classidclsid:8856F961-340A-11D0-A96B-00C04FD705A2 height0/objectfunction printall(){// 打印页面预览 if (!!window.ActiveXObject || ActiveXObject in window){//IE浏览器 $(.noprint).css(display,none); try{//增加打印预览printWB.ExecWB(7, 1);}catch(e){alert(e);}finally{$(.noprint).css(display,); } }else{//需要引入jquery.jqprint-0.3.js$(#a).jqprint();} }附该对象常用的方法
script WebBrowser.ExecWB(1,1) //打开 WebBrowser.ExecWB(2,1) //关闭现在所有的IE窗口并打开一个新窗口 WebBrowser.ExecWB(4,1) //保存网页 //--------------- 常用 --------------- WebBrowser.ExecWB(6,1) //打印 WebBrowser.ExecWB(7,1) //打印预览 WebBrowser.ExecWB(8,1) //打印页面设置 //------------------------------------- WebBrowser.ExecWB(10,1) //查看页面属性 WebBrowser.ExecWB(15,1) //撤销 WebBrowser.ExecWB(17,1) //全选 WebBrowser.ExecWB(22,1) //刷新 WebBrowser.ExecWB(45,1) //关闭窗体无提示
/script 下面附上测试的完整代码
html
head titleprint demo/title meta charsetutf-8 style mediaprint .noprint { display: none; } /style script languageJavaScript function doPrintSetup() { //打印设置 printWB.ExecWB(8, 1) } function doPrintPreview() { if (!!window.ActiveXObject || ActiveXObject in window){ //打印预览 try{printWB.ExecWB(7, 1) }catch(e){alert(e);}}} function doPrint() { //直接打印 printWB.ExecWB(6, 6) } /script
/head body object idprintWB styledispaly:none classidclsid:8856F961-340A-11D0-A96B-00C04FD705A2 height0/objectdiv classnoprint input typebutton value打印设置 onclickdoPrintSetup();/input input typebutton value打印预览 onclickdoPrintPreview();/input input typebutton value直接打印 onclickdoPrint();/input input typebutton value关闭窗口 onclickprintWB.ExecWB(45,1);/input /div p这些文本将要被打印!/p p关于这个组件还有其他的用法列举如下br/ WebBrowser.ExecWB(1,1) 打开br/ Web.ExecWB(2,1) 关闭现在所有的IE窗口并打开一个新窗口br/ Web.ExecWB(4,1) 保存网页br/ Web.ExecWB(6,1) 打印br/ Web.ExecWB(7,1) 打印预览br/ Web.ExecWB(8,1) 打印页面设置br/ Web.ExecWB(10,1) 查看页面属性br/ Web.ExecWB(15,1) 撤销br/ Web.ExecWB(17,1) 全选br/ Web.ExecWB(22,1) 刷新br/ Web.ExecWB(45,1) 关闭窗体无提示br/ /p
/body
/htmlhttps://blog.csdn.net/fengshuiyue/article/details/57483057 原文链接 https://blog.csdn.net/Misnice/article/details/100539347 https://juejin.cn/post/7071064879217508366
https://juejin.cn/post/6844903630135361550 https://blog.csdn.net/ylq090324/article/details/121348777 https://blog.csdn.net/ZslLoveMiwa/article/details/80616399 https://segmentfault.com/a/1190000039696670 https://blog.csdn.net/JAVA11429/article/details/112747188 https://www.cnblogs.com/robertfang/articles/1599551.html https://blog.csdn.net/hehyyoulan/article/details/81098814