携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情 >>
前言
在做一些toB的项目的时候,单据打印和套打是必须要具备的一项功能,接下来我就以我在项目中的实践为例,讲解hiprint在vue中的用法以及源码内的实现。
目录结构
hiprint/
├── css/
│ ├── hiprint.css
│ ├── print-lock.css
├── plugins/
│ ├── JsBarcode.all.min.js
│ └── qrcode.js
│ └── jquery.minicolors.min.js
│ └── jquery.hiwprint.js
├── hiprint.bundle.js
├── polyfill.min.js
从官网下载的hiprint解压后目录结构是这样的,我们需要引入对应的css,polyfill要看你的webpack配置,如果配置了,就无须引入了,plugin可以用external的方式以cdn的形式引入,核心文件就是hiprint.bundle.js,他提供了设计与解析页面。
使用
使用时,我们只需要以import的方式,将hiprint对象引入进来
import hiprint from 'xxx/hiprint/hiprint.bundle.js'
然后调用他的初始化方法init
// 初始化打印插件
hiprint.init({
providers: [new DefaultElementTypeProvider()]
})
注意看下图,init方法是将 传入的配置与原先的配置通过$.extend做了合并,也就是说,这里init直接什么也不传都是可以的。我这里就是重新定义了一下页面上的元素类型
接下来就是解析模版,主要看下图,主要是用到了PrintElementTypeManager,PrintTemplate方法
- PrintElementTypeManager 定义哪些作为设计元素,这里我们是定义了所有包含
ep-draggable-item这个类名的作为设计元素,响应拖拽,每个ep-draggable-item上通过自定义属性tid标识是哪种设计元素
<a class="ep-draggable-item" tid="defaultModule.text" style>
<span
class="glyphicon glyphicon-text-width"
aria-hidden="true"
></span>
<p class="glyphicon-class">文本</p>
</a>
- PrintTemplate 定义当前打印页面的模板是什么,
template定义的是打印的模板json,settingContainer配置对象的dom id,paginationContainer分页对象的dom id,hiprintTemplate.design是定义设计器的dom id
self.hiprintTemplate = new hiprint.PrintTemplate({
template: _customPrintJson,
settingContainer: '#PrintElementOptionSetting',
paginationContainer: '.hiprint-printPagination'
})
// console.log(this.hiprintTemplate.getJson())
// 打印设计
self.hiprintTemplate.design('#hiprint-printTemplate')
self.setCurrentPaper(self.paperMap.A4)
self.elementAddEventListen()
自定义事件是通过hiprint挂在全局的hinnn对象上的event去分发的
然后,你就能看到页面了
核心方法
- px-pt 互转
1pt = 1px * 72 / dpi
1px = 1pt / 72 * dpi
(hinnn.pt = {
toPx: function toPx(t) {
return t * (this.getDpi() / 72);
},
dpi: 0,
getDpi: function getDpi() {
if (!this.dpi) {
var _t2 = document.createElement("DIV");
(_t2.style.cssText =
"width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden"),
document.body.appendChild(_t2),
(this.dpi = _t2.offsetHeight);
}
return this.dpi;
}
}),
(hinnn.px = {
toPt: function toPt(t) {
return t * (72 / this.getDpi());
},
dpi: 0,
getDpi: function getDpi() {
if (!this.dpi) {
var _t3 = document.createElement("DIV");
(_t3.style.cssText =
"width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden"),
document.body.appendChild(_t3),
(this.dpi = _t3.offsetHeight);
}
return this.dpi;
}
}),
- mm转pt/px
(hinnn.mm = {
toPt: function toPt(t) {
return (72 / 25.4) * t;
},
toPx: function toPx(t) {
return hinnn.pt.toPx(hinnn.mm.toPt(t));
}
}),
- toPng
这里,他页面的css单位是mm,所以需要先把毫米转为pt, 然后再把页面上的svg转为了image,拿到页面完整的html,并通过html2canvs方法,转成图片,然后调用系统的window.print方法,将图片进行打印。
- toPdf
这里和toPng大同小异,也是先转为pt,然后通过jsPDF插件将页面转成pdf,然后通过html2canvas先把页面转成图片,然后再把图片添加到pdf实例内,最终返回pdf实例
结语
hiprint 插件上手简单,兼容性也不错,转图片的性能也还可以,针对html2canvas和jspdf的配置也都是经过了作者调优的options,可以说是开箱即用,非常简单,源码虽然经过混淆,但是大部分变量都还在,经过一段时间阅读也能对源码进行有限修改以适配项目需求,建议有页面打印单据需求的同学可以调研一下这个插件