Web 打印开发总结

2018-02-05 10:36:03来源:http://mp.weixin.qq.com/s/0H2Oa7lZbaKc38YIlJHfCw作者:人点击

分享

作者 | 童泽君



介绍:杏仁前端工程师,关注前端各种好玩的技术。


对于经常浏览网页的你来说,打印网页可能并不陌生。我们平时所使用的浏览器在设置菜单都提供了这个功能选项,也可以通过快捷键来(Mac 上是 command + p)触发打印。下面将简单介绍下,在做打印这个不是特别刚性的需求中遇到的一些问题及注意的要点。


怎么实现打印

除了浏览器提供的内置功能选项,在 JavaScript 中可以通过调用 window.print() 方法来实现,调用之后会出现打印预览的对话框。这样做的好处就是我们可以在用户打印之前从服务端获取一些数据然后动态地生成一些内容插入到文档中,这在某些特定的场景中是非常有用的。


@media print

当你打印网页时,你会发现打印预览时的效果往往跟你的预期不是很相符,里面或多或少包含了一些不必要的内容。同样为了给网站提供更好的用户体验,专门为打印的内容应用样式就显得格外重要。


CSS 提供了一种叫做媒体查询的功能,允许我们在不同的媒介应用不同的样式。这个功能在移动端网页较为常见,常用来兼容不同屏幕的样式。为此我们可以通过媒体查询来引入打印所需要的样式,以下是两种引入方式:


<!-- link 标签引入 -->
<link rel="stylesheet" href="print.css" media="print" />
/* index.css */
@media print {
.noprint {
display: none;
}

.printable {
display: block;
}
}

通过在 link 元素上添加media="print"属性就可以为打印应用样式,这种方式的好处就是并不会阻塞页面的首次渲染。注意你选择这种方式的话就不需要在 print.css 中在添加@media pirnt{}了。


另外一种方式就是把打印的样式放到页面首次加载的主 CSS 文件中,用@media print {}包起来就行了。如果你的打印样式比较少的话可以选择这种方式,也就不必要新增一个文件了。


以上的打印样式都只会在打印预览时产生效果,原理其实也挺简单的,就是在打印预览时隐藏不需要打印的元素就行了。


单位 pt

pt 是自然界的标准长度单位,类似于 cm,mm 等,通常用于打印媒体。实际上 1pt 的大小为 1/72 英寸。而我们平时用的 px(像素)通常用于屏幕媒体,虽然也是固定单位,但是根据屏幕的分辨率不同而可大可小。


当然选择哪个单位并没有绝对的。在写这边文章之前,我做打印的需求时都用的是 px,查阅资料后发现对于打印单位都推荐使用 pt,经过一番实践对比后,在不同的设备上(iPad 和 Mac)用 px 打印出来的字体的大小在 iPad 上显得更加纤细,而使用了 pt 的话,差距就不是很明显。还有如果你对 sketch 比较了解的话,你可以对你的 Artboard(画板)类型选为 Paper Sizes(如下图):A4、A5、A6、Letter,纸张类型(比如 A4)后面的大小为 595 x 842,但是是没有单位的。如果你稍微换算一下就知道,A4 的纸张大小为 210mm x 297mm,如果以 pt 为单位的话,换算过来就是 595pt x 842pt。



布局

布局其实跟平时写网页没区别,最省心的方式当然是用 flexbox 来搞定了。但是不建议用浮动,在某些情况下,在电脑端正常但是在 pad 端样式就会错乱,所以尽量避免。如果打印的内容里含有图片,最好是给图片设置一个最大宽度或者最大高度( max-width: 100%ormax-height: 100% ),这样做是为了图片尺寸太大超出纸张大小影响布局。


通常打印的页面往往都会有固定的 header 或 footer,而中间的 body 是根据内容伸缩的,很常见的布局,如下图:



为了显示良好,我们可以用 flexbox 来轻松搞定,但为了兼容性的话也可以用 table 来完成,最终的效果都是相同的,以下为这种布局的伪代码供参考:


// flexbox
.page-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
.page-body {
flex: 1;
}
// table
.page-wrapper {
display: table;
height: 100%;
}
.page-header,
.page-footer {
display: table-row;
height: 1px;
}
.page-body {
display: table;
height: 100%;
}
@page

@page 这个规则很强,可以让我们在 CSS 中设置打印页面的一些属性如:纸张尺寸、边距等。比如以下代码:


@page {
size: A4 landscape;
margin: 2cm;
}

应用上面的 CSS,打印出来的纸张就是 A4 大小,并且纸张的上下左右边距都为 2cm。这个可以确保你输出内容符合预期,用户用着也省心,不用费劲探究各种配置项了。这个规则里面还是有蛮多东西可以设置的,详情请参见 CSS Paged Media Module Level 3 (https://www.w3.org/TR/css3-page/#at-page-rule )


-webkit-print-color-adjust: exact

在打印的对话框中我们可以设置是否打印背景图形,通过这个属性我们可以强制打印的页面有背景图形,即便你在打印对话框中没有勾选背景图形,做这个的好处就是不要用户再费心探究了。当然这是一个非标准属性,以后可能会更改,目前在 Chrome、Safari 是有效的,Firefox 上不生效。


分页

对于分页问题,CSS 早在 2.x 版本中就支持了一些属性用来控制元素的分页行为。如 page-break-before,page-break-after,page-break-inside,在元素上应用这些属性就可以控制在该元素之前或之后,或者元素内部是否分页。这几个属性的取值这里就不一一列出了,请自行探究。


在实际的场景往往不是很简单,页面上超出的内容可能需要以某种样式整齐的放在下一页,这些属性并不能带来想要的效果,因此还要用


JavaScript 来操作 DOM 来处理分页问题。思路也比较简单,就是如果内容超出了纸张大小就去截取超出内容并放到下一页。


总结

以上是做打印需求的一些简单总结及实践,并不是很全面深入,希望能让各位前端同学们做同样的需求时,少走一些弯路。


参考

CSS print 样式:http://www.css88.com/archives/4731


Print—被埋没的Media Type:http://cdc.tencent.com/2014/08/19/print-被埋没的media-type/


CSS:EM, PX, PT, CM, IN…:https://www.w3.org/Style/Examples/007/units.zh_CN.html


CSS 打印:http://lon.im/post/css-print.html


全文完


以下文章您可能也会感兴趣:


四维阅读法 - 我的高效学习“秘技”


工程师成长的必备技能


iOS 屏幕适配浅谈


Web 与 App 数据交互原理和实现


苹果在医疗健康领域的三个 Kit


聊聊移动端跨平台数据库 Realm


复杂业务状态的处理:从状态模式到 FSM


如何成为一名数据分析师:数据的初步认知


从 React 到 Preact 迁移指南


后端的缓存系统浅谈


Objective-C 中的语法糖


Android 图片编辑的原理与实现——涂鸦与马赛克





杏仁技术站

长按左侧二维码关注我们,这里有一群热血青年期待着与您相会。




最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台