使用LitElement编写一个文档扫描的Web Component

Lit是一个用于构建快速轻量的Web Component的库。Lit的核心是一个用于编写组件的基类,它提供了响应性的状态、作用域内的样式和一个小巧的声明式模板系统。

在本文中,我们将使用LitElement编写一个Web Component,基于Dynamic Web TWAIN实现在浏览器中扫描文档。

新建项目

虽然Lit可以在没有构建系统的情况下使用,但在本文中,我们使用webpack (克隆下面的模板项目) :

bash 复制代码
git clone https://github.com/wbkd/webpack-starter

安装依赖项

  1. 安装Lit。

    bash 复制代码
    npm install lit
  2. 安装Dynamic Web TWAIN。

    bash 复制代码
    npm install dwt

    此外,我们需要将Dynamic Web TWAIN的资源文件复制到public文件夹中。

    1. 安装ncp

      bash 复制代码
      npm install --save-dev ncp
    2. 修改package.json的build和start命令以复制资源。

      diff 复制代码
       "scripts": {
         "lint": "npm run lint:styles; npm run lint:scripts",
         "lint:styles": "stylelint src",
         "lint:scripts": "eslint src",
         "build": "cross-env NODE_ENV=production webpack --config webpack/webpack.config.prod.js",
         "start": "webpack serve --config webpack/webpack.config.dev.js"
      +  "build": "ncp node_modules/dwt/dist public/dwt-resources && cross-env NODE_ENV=production webpack --config webpack/webpack.config.prod.js",
      +  "start": "ncp node_modules/dwt/dist public/dwt-resources && webpack serve --config webpack/webpack.config.dev.js"
       },
    3. 修改webpack.common.js以将public文件夹中的文件直接复制到输出文件夹,而不是输出文件夹中的public文件夹。

      diff 复制代码
       new CopyWebpackPlugin({
      -  patterns: [{ from: Path.resolve(__dirname, '../public'), to: 'public' }],
      +  patterns: [{ from: Path.resolve(__dirname, '../public'), to: '' }],
       }),

编写文档扫描组件

  1. 使用以下模板在src\scripts下创建新的documentscanner.js文件。

    js 复制代码
    import {LitElement, html, css} from 'lit';
    
    export class DocumentScanner extends LitElement {
      static properties = {
      };
      DWObject;
      static styles = css`
        :host {
          display: block;
        }
        `;
      constructor() {
        super();
      }
    
      render() {
        return html``;
      }
    }
    customElements.define('document-scanner', DocumentScanner);
  2. 添加一个div元素作为Dynamic Web TWAIN控件的容器(主要用于显示文档)。

    js 复制代码
    render() {
      return html`<div id="dwtcontrolContainer"></div>`;
    }
  3. constructor中配置Dynamic Web TWAIN。需要一个许可证来使用Dynamic Web TWAIN。可以在此处申请许可证。

    js 复制代码
    constructor() {
      super();
      Dynamsoft.DWT.AutoLoad = false;
      Dynamsoft.DWT.ResourcesPath = "/dwt/dist";
      Dynamsoft.DWT.ProductKey = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; //one-day trial
    }
  4. 在DOM首次更新后的firstUpdated生命周期中初始化Dynamic Web TWAIN ,并将其绑定到上一步创建的容器。此外,发送一个自定义事件以发送Dynamic Web TWAIN的实例,这样我们可以在父元素中访问它。

    js 复制代码
    DWObject;
    firstUpdated() {
      let pThis = this;
      let dwtContainer = this.renderRoot.getElementById("dwtcontrolContainer");
      Dynamsoft.DWT.CreateDWTObjectEx(
        {
          WebTwainId: 'dwtcontrol'
        },
        function(obj) {
          pThis.DWObject = obj;
          pThis.DWObject.Viewer.bind(dwtContainer);
          pThis.DWObject.Viewer.show();
          pThis.DWObject.Viewer.width = "100%";
          pThis.DWObject.Viewer.height = "100%";
          const event = new CustomEvent('initialized', {
            detail: {
              DWObject: pThis.DWObject
            }
          });
          pThis.dispatchEvent(event);
        },
        function(err) {
          console.log(err);
        }
      );
    }
  5. 添加一个扫描文档的按钮和一个将文档图像保存为PDF文件的按钮。

    js 复制代码
    render() {
      return html`
      <div class="buttons">
        <button @click=${this.scan}>Scan</button>
        <button @click=${this.save}>Save</button>
      </div>
      <div id="dwtcontrolContainer"></div>`;
    }
    scan(){
      let pThis = this;
      if (pThis.DWObject) {
        pThis.DWObject.SelectSource(function () {
          pThis.DWObject.OpenSource();
          pThis.DWObject.AcquireImage();
        },
          function () {
            console.log("SelectSource failed!");
          }
        );
      }
    }
    
    save(){
      if (this.DWObject) {
        this.DWObject.SaveAllAsPDF("Scanned.pdf");
      }
    }
  6. 添加名为total的响应性属性,以反映扫描的文档页面数量。我们可以在Web TWAIN的OnBufferChanged事件中更新它的值。

    js 复制代码
    export class DocumentScanner extends LitElement {
      static properties = {
        total: {},
      };
      constructor() {
        super();
        this.total = 0;
        //...
      }
      render() {
        return html`
        <div class="buttons">
          <button @click=${this.scan}>Scan</button>
          <button @click=${this.save}>Save</button>
        </div>
        <div id="dwtcontrolContainer"></div>
        <div class="status">Total: ${this.total}</div>`;
      }
    
      firstUpdated() {
        //...
        Dynamsoft.DWT.CreateDWTObjectEx(
          {
            WebTwainId: 'dwtcontrol'
          },
          function(obj) {
            //...
            pThis.DWObject.RegisterEvent('OnBufferChanged',function () {
              pThis.total = pThis.DWObject.HowManyImagesInBuffer;
            });
            //...
          },
          function(err) {
            console.log(err);
          }
        );
      }
    }
  7. 设置组件的样式。

    js 复制代码
    static styles = css`
      :host {
        display: block;
      }
      .buttons {
        height: 25px;
      }
      #dwtcontrolContainer {
        width: 100%;
        height: calc(100% - 50px);
      }
      .status {
        height: 25px;
      }
      `;

使用文档扫描组件

  1. index.js文件中导入组件。

    js 复制代码
    import { DocumentScanner } from './documentscanner'; // eslint-disable-line
  2. index.html中添加组件。

    html 复制代码
    <document-scanner
      style="width:320px;height:480px;"
    ></document-scanner>

好了,我们现在可以从浏览器扫描文档了。

在线demo

源代码

欢迎下载源代码并尝试使用:

github.com/tony-xlh/do...

相关推荐
weixin_382395233 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__3 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.3 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~4 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华5 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子7 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅8 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni8 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学9 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端