前言:该文章须要必定的electron基础同窗。如需了解更多相关信息,请移步electron官方文档。html
公司项目须要经过electron调用系统打印机,实现打印小票的功能。
复制代码
electron打印大概有两种:
第一种:经过window的webcontent对象,使用此种方式须要单独开出一个打印的窗口,能够将该窗口隐藏,可是通讯调用相对复杂。
第二种:使用页面的webview元素调用打印,能够将webview隐藏在调用的页面中,通讯方式比较简单。
两个对象调用打印方法的使用方式都同样。
本文是经过第二种方法实现静默打印。
复制代码
一、要实现打印功能,首先要知道咱们的设备上有哪些打印机。方法是:在渲染线程经过electron的ipcRenderer对象发送事件到主线程获取。(本文的渲染线程能够当作为一个print.vue文件)vue
(1)主线程(electron.js)伪代码以下:
//引入electron
import electron from 'electron';
//建立一个浏览器对象
const window = new electron.BrowserWindow({
width,
height,
frame: false,
show: false,
backgroundColor: '#4b5b79',
minWidth: 1024,
minHeight: 768,
webPreferences: { webSecurity: false },
});
//在主线程下,经过ipcMain对象监听渲染线程传过来的getPrinterList事件
electron.ipcMain.on('getPrinterList', (event) => {
//主线程获取打印机列表
const list = window.webContents.getPrinters();
//经过webContents发送事件到渲染线程,同时将打印机列表也传过去
window.webContents.send('getPrinterList', list);
});
===============================================================================
复制代码
print.vue文件node
(2)渲染线程(print.vue文件)伪代码以下:
<template>
</template>
<script>
//引入ipcRenderer对象,该对象和主线程的ipcMain通信
import { ipcRenderer } from 'electron';
//渲染线程主动发送getPrinterList事件到主线程请求打印机列表
ipcRenderer.send('getPrinterList');
//监听主线程获取到打印机列表后的回调
ipcRenderer.once('getPrinterList', (event, data) => {
//data就是打印机列表
this.printList = data;
});
</script>
//获取打印机列表完成
复制代码
二、(重头戏来了)获取打印机列表后,就须要经过electron自带的"webview"标签实现小票排版。"webview"是什么?能够把它当作"iframe"标签,它里面显示的是你须要打印的内容。web
(1)使用"webview"以前,须要新建一个print.html文件,把你要打印的内容经过print.html显示出来。咱们项目的需求是将要打印的内容经过canvas画出后,再将canvas转成图片资源(base64),而后放到"webview"里面显示.具体作法是:在渲染线程(print.vue)作一系列逻辑,最终生成base64资源,而后经过webview.send()定义一个'webview-print-render'事件,该事件能够和print.html页面通信,将base64传给print.html页面作展现,print.vue伪代码以下:canvas
<template>
<div v-show="false">
<webview ref="printWebview" src="./xxxx/print.html" nodeintegration/>
</div>
</template>
<script>
methods: {
printRender(imgsrc) {
// 获取<webview>节点
const webview = this.$refs.printWebview;
// 发送信息到<webview>里的页面
webview.send('webview-print-render', {
printName: this.printDeviceName, //打印机名称
imgSource: imgsrc, // base64图片
});
},
}
</script>
复制代码
print.html代码:浏览器
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
//@page样式是用来设置打印机打印出来的样式,例如设置小票外边距样式
@page {
margin: 0px;
}
</style>
</head>
<body id='bd'>
</body>
<script>
//引入ipcRenderer对象
const {ipcRenderer} = require('electron')
//监听渲染线程传过来的webview-print-render事件
ipcRenderer.on('webview-print-render', (event, deviceInfo) => {
// 动态建立一个img标签,而后插入到<body>中。deviceInfo是渲染线程传过来的数据
let html = '';
html = `<img src="${deviceInfo.imgSource}"
width="${deviceInfo.imgWidth}px"
height="${deviceInfo.imgHeight}px">`;
document.getElementById('bd').innerHTML = html;
//当图片插入到页面后,经过ipcRenderer对象的sendToHost方法和渲染线程通信,告诉渲染线程打印的内容已经准备完毕,请开始打印操做
ipcRenderer.sendToHost('webview-print-do');
});
</script>
</html>
复制代码
(2)html文件建立完成后,将print.html引入到《webview src="./xxxx/print.html"》。该"webview"须要显式的定义在print.vue文件中,但须要将它用v-show="false"隐藏,不能用v-if,由于咱们须要"webview"的dom节点存在于页面上,只是不展现而已。dom
<template>
<div v-show="false">
<webview ref="printWebview" src="./xxxx/print.html" nodeintegration/>
</div>
</template>
<script>
mounted() {
//当vue节点渲染完成后,获取<webview>节点
const webview = this.$refs.printWebview;
//监听<webview>里面的消息,也就是监听print.html里面的ipcRenderer.sendToHost发送的事件,当该事件发送成功后就会进入下面的回调事件中执行打印操做。
webview.addEventListener('ipc-message', (event) => {
if (event.channel === 'webview-print-do') {
//若是收到<webview>传过来的事件,名为"webview-print-do",就执行 webview.print打印方法,打印<webview>里面的内容。
webview.print(
{
//是不是静默打印
silent: true,
printBackground: true,
//打印机的名称,就是本文一开始得到的打印机列表其中一个
deviceName: 'xxx',
},
(data) => {
//这个回调是打印后的回调事件,data为true就是打印成功,为false就打印失败
console.log('webview success', data);
},
);
}
});
},
</script>
复制代码
到这里本electron调用打印机的功能就实现了。但本文章有不少细节没有讲到,只是大概的给了一个思路,若是写的有不对之处,还望见谅。electron