使用Electron构建跨平台文档扫描应用程序

Electron是一个用于与HTML,JavaScript和CSS一起构建跨平台桌面应用程序的框架。 由于Dynamic Web TWAIN也是一个用于扫描文档的跨平台JavaScript库,因此使用Electron for Windows,Linux和macOS实现桌面文档扫描应用程序非常容易。

安装准备:

Dynamic Web TWAIN SDK
• Electron:
npm install -g electron

使用electron构建应用程序:

参考文档
Electron Documentation

Electron 应用程序的结构
一个Electron应用程序的结构如下:

app/
├── package.json
├── main.js
└── index.html

你知道如何为Node.js模块编写package.json文件吗? 步骤完全相同。 我是这么做的:

{
  "name": "docscanner",
  "version": "1.0.0",
  "description": "Cross-platform document scanning application for Windows, Linux and macOS",
  "main": "main.js",
  "scripts": {
  "start": "electron main.js"
  },
  "repository": {
  "type": "git",
  "url": "git+https://github.com/yushulx/electron-document-scan.git"
  },
  "keywords": [
  "Dynamsoft",
  "document scan",
  "web twain",
  "SDK"
  ],
  "author": "yushulx",
  "homepage": "http://www.dynamsoft.com/Products/WebTWAIN_Overview.aspx",
  "devDependencies": {
  "electron-prebuilt": "^1.6.1"
  }
}

使用将由Electron加载的JavaScript文件指定主字段。 此外,您需要创建index.html以使用HTML和CSS呈现UI。 阅读Electron API参考时,您可能会看到主进程和渲染进程。 它们是什么以及如何使用相关API?

电子主要进程
主进程是运行main.js的入口点。 它创建渲染进程并管理本机元素。 完整的Node API是内置的。

电子渲染进程
渲染进程是运行index.html的浏览器窗口。 Electron使开发人员能够在网页中使用Node.js API。

文档扫描应用程序

根据Electron文档,我们只需要将所有工作放在index.html中并使用main.js加载它。

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Document Scanner</title>
  <script type="text/javascript" src="http://www.dynamsoft.com/library/dwt/dynamsoft.webtwain.min.js"></script>
  <style>
  h1 {
  font-size: 2em;
  font-weight: bold;
  color: #777777;
  text-align: center
  }
   
  table {
  margin: auto;
  }
  </style>
</head>
 
<body>
  <h1>
  Document Scanner
  </h1>
  We are using node
  <script>
  document.write(process.versions.node)
  </script>, Chrome
  <script>
  document.write(process.versions.chrome)
  </script>, and Electron
  <script>
  document.write(process.versions.electron)
  </script>.
  <table>
  <tr>
  <td>
  <!-- dwtcontrolContainer is the default div id for Dynamic Web TWAIN control.
  If you need to rename the id, you should also change the id in dynamsoft.webtwain.config.js accordingly. -->
  <div id="dwtcontrolContainer"></div>
  </td>
  </tr>
 
  <tr>
  <td>
  <input type="button" value="Scan" "scanImage();" />
  <input type="button" value="Load" "loadImage();" />
  <input type="button" value="Save" "saveImage();" />
  </td>
  </tr>
  </table>
 
  <script type="text/javascript">
  var console = window['console'] ? window['console'] : {
  'log': function() {}
  };
  Dynamsoft.WebTwainEnv.RegisterEvent('OnWebTwainReady', Dynamsoft_OnReady); // Register OnWebTwainReady event. This event fires as soon as Dynamic Web TWAIN is initialized and ready to be used
 
  var DWObject;
 
  function Dynamsoft_OnReady() {
  DWObject = Dynamsoft.WebTwainEnv.GetWebTwain('dwtcontrolContainer'); // Get the Dynamic Web TWAIN object that is embeded in the div with id 'dwtcontrolContainer'
  if (DWObject) {
  DWObject.RegisterEvent('OnPostAllTransfers', SaveWithFileDialog);
  }
  }
 
  function scanImage() {
  if (DWObject) {
  var bSelected = DWObject.SelectSource();
 
  if (bSelected) {
  var OnAcquireImageSuccess, OnAcquireImageFailure;
  OnAcquireImageSuccess = OnAcquireImageFailure = function() {
  DWObject.CloseSource();
  };
 
  DWObject.OpenSource();
  DWObject.IfDisableSourceAfterAcquire = true; // Scanner source will be disabled/closed automatically after the scan. 
  DWObject.AcquireImage(OnAcquireImageSuccess, OnAcquireImageFailure);
  }
  }
  }
 
  //Callback functions for async APIs
  function OnSuccess() {
  console.log('successful');
  }
 
  function OnFailure(errorCode, errorString) {
  alert(errorString);
  }
 
  function loadImage() {
  if (DWObject) {
  DWObject.IfShowFileDialog = true; // Open the system's file dialog to load image
  DWObject.LoadImageEx("", EnumDWT_ImageType.IT_ALL, OnSuccess, OnFailure); // Load images in all supported formats (.bmp, .jpg, .tif, .png, .pdf). OnSuccess or OnFailure will be called after the operation
  }
  }
 
  function saveImage() {
  if (DWObject) {
  if (DWObject.HowManyImagesInBuffer > 0) {
  DWObject.IfShowFileDialog = true;
  if (DWObject.GetImageBitDepth(DWObject.CurrentImageIndexInBuffer) == 1) {
  DWObject.ConvertToGrayScale(DWObject.CurrentImageIndexInBuffer);
  }
  DWObject.SaveAsJPEG("DynamicWebTWAIN.jpg", DWObject.CurrentImageIndexInBuffer);
  }
  }
  }
  </script>
</body>
 
</html>

main.js

'use strict';
 
const { app, BrowserWindow } = require('electron');
 
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
 
function createWindow() {
  // Create the browser window.
  mainWindow = new BrowserWindow({ width: 480, height: 640, resizable: false });
 
  // and load the index.html of the app.
  mainWindow.loadURL('file://' + __dirname + '/index.htm');
 
  // Open the DevTools.
  // mainWindow.webContents.openDevTools();
 
  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
  // Dereference the window object, usually you would store windows
  // in an array if your app supports multi windows, this is the time
  // when you should delete the corresponding element.
  mainWindow = null;
  });
}
 
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', createWindow);
 
// Quit when all windows are closed.
app.on('window-all-closed', function() {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
  app.quit();
  }
});
 
app.on('activate', function() {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
  createWindow();
  }
});

运行应用程序
运行APP

应用分发

要分发应用程序,有两个步骤:

第一步,用asar打包应用程序。

npm install -g asar
asar pack your-app app.asar

第二步,下载Electron prebuilt package 并将app.asar放入资源文件夹。
资源文件夹
默认情况下有两个asar文件,可以将它们留在那里。 您可以双击electron.exe在Windows上运行该应用程序。

Source Code

https://github.com/yushulx/electron-document-scan