发布于 5年前

JavaScript使用window.print()打印页面:样式设置、精确分页以及局部打印

大部分浏览器提供打印页面的功能,直接使用浏览器的打印功能是直接将整个页面打印出来,并且是自动分页。

很多时候直接打印整个页面并不能满足我们的需要。有三方面的需求我们可能要考虑:

  1. 样式设置:打印的样式和页面显示的样式不同,需要对设置打印样式。
  2. 精确分页:需要根据具体的内容进行精确分页。
  3. 局部打印:不需要打印整个页面,只需要打印页面的部分。

html示例

<!doctype html> 
<html> 
<head> 
    <meta charset="utf-8"> 
    <title>打印</title> 
</head> 
<body> 
    <div>内容1</div> 
    <div>内容2</div> 
    <input onclick="print()" value="点击打印" type="button"> 
</body>
</html> 

样式设置

页面打印默认会应用当前的样式。如果我们需要对打印的样式做定制的设置,可以使用@media print媒体属性。@media print里定义的样式只会应用于打印,不会应用于页面显示。

例如让内容1的字体打印为斜体:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>打印</title>
<style>
@media print{
  .italic {font-style: italic}
}
</style>
</head>
<body>
<div class="italic">内容1</div>
<div>内容2</div>
<input onclick="print()" value="点击打印" type="button">
</body>
</html>

精确分页

默认情况下,调用window.print()会根据页面的内容自动分页。如示例,因为页面的内容少,在一个打印页面就可以容纳,所以是不会分页。

但如果有需求要把"内容1"和“内容2”分为两页打印,那该怎么办呢?

CSS的page-break-after属性可以用来做分页,它的值为:

  • auto:默认。如果必要则在元素后插入分页符。
  • always:在元素后插入分页符。
  • avoid:避免在元素后插入分页符。
  • left:在元素之后足够的分页符,一直到一张空白的左页为止。
  • right:在元素之后足够的分页符,一直到一张空白的右页为止。
  • inherit:规定应该从父元素继承 page-break-after 属性的设置。

auto和always所有浏览器都支持,后面四个值浏览器支持程度不同。

添加page-break-after:always精确分页:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>打印</title>
<style>
@media print{
  .page-break {page-break-after:always;}
}
</style>
</head>
<body>
<div class="page-break">内容1</div>
<div>内容2</div>
<input onclick="print()" value="点击打印" type="button">
</body>
</html>

局部打印

默认情况下,window.print()会把整个页面打印处理。如示例里的按钮“点击打印"也是会被打印出来,显然这是我们不想要的。

有两种方法可以对实现局部打印:

  1. 对不打印的内容隐藏起来
  2. 把打印的内容添加到新的窗口打印

隐藏打印内容

CSS有两个属性可以用来隐藏显示内容:

  • visibility:设置为hidden,内容不显示,但是在内容显示的地方会变成空白。
  • display:设置为none。内容会被隐藏,原来内容所在的元素如同删除一样,不显示空白。

一般情况下,打印页面会使用display:none。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>打印</title>
<style>
@media print{
  .page-break {page-break-after:always;}
  .nonprint{display:none}
}
</style>
</head>
<body>
<div class="page-break">内容1</div>
<div>内容2</div>
<input class="nonprint" onclick="print()" value="点击打印" type="button">
</body>
</html>

在新窗口打印

但要打印的内容少,不打印的内容多且分散,这种情况下隐藏不打印内容就不太好。一般的策略是新建一个窗口,把要打印的内容添加到新的窗口在打印。

需要注意的是:把打印内容添加到新窗口不要把样式添加进去。

示例

printInNewWindow(containerId, style) {
  var html = document.getElementById(containerId).innerHTML;
  var win= window.open('', '打印', 'height=400,width=600'); 

  win.document.write('<html><head><title></title>'); 
  win.document.write('<style>'+style+'</style>'); 
  win.document.write('</head><body >'); 
  win.document.write(html); 
  win.document.write('</body></html>'); 
  win.document.close();  // IE >= 10 不能少
  win.focus();           // IE >= 10
  win.print(); 
  win.close(); 
}

当然,样式也可以使用css文件。在新窗口打开需要加载css文件,在调用打印前最好调用setTimeout()做下延时。

示例

printInNewWindow(containerId, cssLinks) {
  var html = document.getElementById(containerId).innerHTML;
  var win= window.open('', '打印', 'height=400,width=600'); 

  win.document.write('<html><head><title></title>');
  if(cssLinks && cssLinks.length > 0) {
    cssFiles.forEach((cssLink) => {
      win.document.write('<link rel="stylesheet" href="'+ cssLink +'" type="text/css" />');
    });
  } 
  win.document.write('</head><body >'); 
  win.document.write(html); 
  win.document.write('</body></html>'); 
  win.document.close();  // IE >= 10 不能少
  win.focus();           // IE >= 10
  setTimeout(()=> {     //延时
   win.print(); 
   win.close();
  },500);
}

总结

本文主要介绍了如何解决window.print()打印页面时可能要考虑的三个问题:样式设置、精确分页以及局部打印。除了使用window.print()。jquery也提供了一个用于打印的插件PrintArea

©2020 edoou.com   京ICP备16001874号-3