vCard名片二维码在前端的生成与扫描

vCard又名VCF("虚拟联系人文件"),是电子名片的文件格式标准。以下是vCard文件内容的一个示例:

makefile 复制代码
BEGIN:VCARD
VERSION:4.0
FN:Simon Perreault
N:Perreault;Simon;;;ing. jr,M.Sc.
BDAY:--0203
GENDER:M
EMAIL;TYPE=work:simon.perreault@viagenie.ca
END:VCARD

vCard可通过电子邮件、聊天应用、NFC或网络链接等方式进行分享。不过更方便的方法是扫描二维码。例如用iPhone的相机应用扫描以下二维码,会提示添加联系人。

在本文中,我们将构建一个用于生成vCard二维码的HTML页面,以及另一个基于Dynamsoft Barcode Reader SDK扫描二维码的页面。我们自己编写一个扫描vCard的应用的好处是,可以与Salesforce和Dynamics 365等CRM系统集成,方便管理联系人。

演示视频

生成vCard二维码

我们将使用两个第三方库:

  1. 创建一个新的HTML文件并引用上述库。

    html 复制代码
    <!DOCTYPE html>
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>vCard QR Code Generator</title>
      <style>
      </style>
      <script type="text/javascript" src="qrcode.js"></script>
      <script type="module">
        import VCard from 'https://cdn.skypack.dev/vcard-creator'
        window.VCard = VCard;
      </script>
    </head>
    <html>
    <body>
      <div id="app">
        <h2>vCard QR Code Generator</h2>
      </div>
      <script>
      </script>
    </body>
    </html>
  2. 创建一个表单来输入联系人信息。

    html 复制代码
    <div class="form">
      <label>
        First name:
        <input type="text" id="firstName"/>
      </label>
      <label>
        Last name:
        <input type="text" id="lastName"/>
      </label>
      <label>
        Phone:
        <input type="text" id="phone"/>
      </label>
      <label>
        Email:
        <input type="text" id="email"/>
      </label>
      <label>
        Company:
        <input type="text" id="company"/>
      </label>
      <label>
        Job title:
        <input type="text" id="jobTitle"/>
      </label>
      <label>
        Website:
        <input type="text" id="website"/>
      </label>
      <button id="generateButton">Generate</button>
    </div>
  3. 使用输入的信息生成二维码。

    html 复制代码
    <div id="placeHolder"></div>
    <script>
    document.getElementById("generateButton").addEventListener("click",generateQRCode);
    function generateQRCode(){
      const card = new VCard()
      const firstName = document.getElementById("firstName").value;
      const lastName = document.getElementById("lastName").value;
      const phone = document.getElementById("phone").value;
      const company = document.getElementById("company").value;
      const jobTitle = document.getElementById("jobTitle").value;
      const website = document.getElementById("website").value;
      const email = document.getElementById("email").value;
      card.addName(lastName, firstName, "", "", "")
        .addCompany(company)
        .addJobtitle(jobTitle)
        .addEmail(email)
        .addPhoneNumber(phone, 'WORK')
        .addURL(website)
      const vcf = card.toString();
      console.log(vcf);
      generateQR(vcf);
    }
    function generateQR(content){
      try {
        var typeNumber = 0;
        var errorCorrectionLevel = 'L';
        var qr = qrcode(typeNumber, errorCorrectionLevel);
        qr.addData(content);
        qr.make();
        var placeHolder = document.getElementById('placeHolder');
        placeHolder.innerHTML = qr.createSvgTag();  
      } catch (error) {
        alert(error);
      }
    }
    </script>
  4. 我们还可以使用现有的vcf文件生成二维码。

    html 复制代码
    <button id="generateWithExistingButton">Generate with an existing vcf file</button>
    <input style="display:none;" type="file" id="file" onchange="loadFromFile();" accept=".vcf"/>
    <script>
    document.getElementById("generateWithExistingButton").addEventListener("click",function(){
      document.getElementById("file").click();
    });
    
    function loadFromFile(){
      let fileInput = document.getElementById("file");
      let files = fileInput.files;
      if (files.length == 0) {
        return;
      }
      let file = files[0];
      fileReader = new FileReader();
      fileReader.onload = function(e){
        generateQR(e.target.result);
      };
      fileReader.onerror = function () {
        console.warn('oops, something went wrong.');
      };
      fileReader.readAsText(file);
    }
    </script>

请注意,一个二维码只能包含约2KB的数据。如果需要传输更多数据,可以尝试动态二维码的方法。

扫描vCard二维码

接下来,创建一个页面来扫描vCard二维码。

新建HTML文件

创建一个包含以下内容的新HTML文件:

html 复制代码
<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>vCard QR Code Scanner</title>
  <style>
  h2 {
    text-align: center;
  }

  #app {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  #cameraView {
    width: 100%;
    height: 60vh;
  }
  </style>
</head>
<html>
<body>
  <div id="app">
    <h2>vCard Scanner</h2>
    <button id="startScanBtn">Start Scanning</button>
    <button id="readFromImageBtn">Read from an Image</button>
    <input id="fileInput" type="file" style="display:none;"/>
    <div id="status">Loading...</div>
    <div id="cameraView"></div>
    <div id="result"></div>
  </div>
</body>
</html>

添加Dynamsoft Barcode Reader

添加下面的代码以引入Dynamsoft Barcode Reader:

html 复制代码
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@10.4.2000/dist/dbr.bundle.js"></script>

然后,初始化Dynamsoft Barcode Reader。

  1. 初始化许可证。可以在此处申请许可证

    js 复制代码
    Dynamsoft.License.LicenseManager.initLicense("LICENSE-KEY");
  2. 加载WASM文件。

    js 复制代码
    Dynamsoft.Core.CoreModule.loadWasm(["dbr"]);
  3. 创建capture vision router实例以调用Dynamsoft Barcode Reader。

    js 复制代码
    let cvRouter = await Dynamsoft.CVR.CaptureVisionRouter.createInstance();

打开摄像头扫描

  1. 初始化Camera Enhancer并将其组件绑定到一个容器。

    js 复制代码
    let cameraView = await Dynamsoft.DCE.CameraView.createInstance();
    let cameraEnhancer = await Dynamsoft.DCE.CameraEnhancer.createInstance(cameraView);
    document.querySelector("#cameraView").append(cameraView.getUIElement());
  2. 使用Camera Enhancer作为capture vision router的输入,这样它就可以从摄像头获取帧来读取条形码。

    js 复制代码
    cvRouter.setInput(cameraEnhancer);
  3. 添加结果接收器以接收扫描结果。

    js 复制代码
    cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => {
      displayResults(result);
    }});
    
    function displayResults(result){
      if (result.barcodeResultItems.length > 0) {
        let container = document.getElementById("result");
        let item = result.barcodeResultItems[0];
        console.log(item);
      }
    }
  4. 单击扫描按钮后开始扫描。

    js 复制代码
    let templateName = "ReadSingleBarcode"
    await cameraEnhancer.open();
    await cvRouter.startCapturing(templateName);

解析vCard

接下来,解析vCard的文本并显示联系人信息。

html 复制代码
<!-- https://github.com/Heymdall/vcard/ -->
<script type="text/javascript" src="vcf.js"></script>
<script>
function formatedContactInfo(barcodeText) {
  try {
    let parsed = parse(barcodeText);
    let presetKeys = {"fn":"Full name","org":"Organization","title":"Job Title","url":"URL","tel":"Tel","email":"Email"};
    let str = "";
    for (let index = 0; index < Object.keys(presetKeys).length; index++) {
      const key = Object.keys(presetKeys)[index];
      const value = presetKeys[key];
      if (key in parsed) {
        let appendedValue = "";
        let valueArray = parsed[key];
        valueArray.forEach(valueObject => {
          appendedValue = appendedValue + valueObject.value + "\n";
        });
        str = str + value + ": " +appendedValue.trim() + "\n";
      }
    }
    vCardContent = barcodeText;
    document.getElementsByClassName("buttons")[0].removeAttribute("hidden");
    return str;
  } catch (error) {
    return "Invalid vCard."
  }
}
</script>

下载为VCF文件

我们可以将vCard下载为.vcf文件。它可以通过系统的联系人应用程序打开。

js 复制代码
function downloadText(){
  let filename = 'scanned.vcf';
  let link = document.createElement('a');
  link.style.display = 'none';
  link.setAttribute('target', '_blank');
  link.setAttribute('href', 'data:text/vcard;charset=utf-8,' + encodeURIComponent(vCardContent));
  link.setAttribute('download', filename);
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

读取图像中的二维码

除了实时扫描,我们还可以读取图像中的vCard二维码。

添加用于选择图像文件的事件。选择图像后,使用capture方法识别其中的条码。

js 复制代码
document.getElementById("readFromImageBtn").addEventListener("click",function(){
  if (initialized) {
    document.getElementById("fileInput").click();
  }else{
    alert("Please wait for the initialization.");
  }
});
document.getElementById("fileInput").addEventListener("change",async function(){
  let files = document.getElementById("fileInput").files;
  if (files.length>0) {
    let file  = files[0];
    let result = await cvRouter.capture(file,templateName);
    displayResults(result);
  }
})

好了,demo已经编写好了。

源代码

获取源代码来自己试用一下吧:

相关推荐
方也_arkling5 分钟前
别名路径联想提示。@/统一文件路径的配置
前端·javascript
毕设源码-朱学姐8 分钟前
【开题答辩全过程】以 基于web教师继续教育系统的设计与实现为例,包含答辩的问题和答案
前端
qq_1777673713 分钟前
React Native鸿蒙跨平台剧集管理应用实现,包含主应用组件、剧集列表、分类筛选、搜索排序等功能模块
javascript·react native·react.js·交互·harmonyos
qq_1777673719 分钟前
React Native鸿蒙跨平台自定义复选框组件,通过样式数组实现选中/未选中状态的样式切换,使用链式调用替代样式数组,实现状态驱动的样式变化
javascript·react native·react.js·架构·ecmascript·harmonyos·媒体
web打印社区22 分钟前
web-print-pdf:突破浏览器限制,实现专业级Web静默打印
前端·javascript·vue.js·electron·html
RFCEO41 分钟前
前端编程 课程十三、:CSS核心基础1:CSS选择器
前端·css·css基础选择器详细教程·css类选择器使用方法·css类选择器命名规范·css后代选择器·精准选中嵌套元素
烬头88211 小时前
React Native鸿蒙跨平台采用了函数式组件的形式,通过 props 接收分类数据,使用 TouchableOpacity实现了点击交互效果
javascript·react native·react.js·ecmascript·交互·harmonyos
Amumu121381 小时前
Vuex介绍
前端·javascript·vue.js
We་ct1 小时前
LeetCode 54. 螺旋矩阵:两种解法吃透顺时针遍历逻辑
前端·算法·leetcode·矩阵·typescript
2601_949809591 小时前
flutter_for_openharmony家庭相册app实战+相册详情实现
javascript·flutter·ajax