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已经编写好了。

源代码

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

相关推荐
初心丨哈士奇2 分钟前
基于大模型的GitLab CodeReview 技术调研
前端·人工智能·node.js
Aphasia3117 分钟前
Web身份认证与状态管理:Cookie、Session 与 JWT
前端·面试
鱼樱前端8 分钟前
基于Vue3+Ts+Vant的高级图片上传组件
前端·javascript·vue.js
ChangYan.9 分钟前
electron builder打包时,出现errorOut=ERROR: Cannot create symbolic link
前端·javascript·electron
冴羽23 分钟前
SvelteKit 最新中文文档教程(1)—— 入门指南
前端·javascript·svelte
冬冬小圆帽43 分钟前
防抖和节流
开发语言·前端·javascript
周努力.1 小时前
关于Vue/React中Diffing算法以及key的作用
javascript·vue.js·react.js
lydxwj1 小时前
vue3自定义hooks遇到的问题
前端·javascript·vue.js
野生的程序媛1 小时前
重生之我在学Vue--第8天 Vue 3 UI 框架(Element Plus)
前端·vue.js·ui
前端付杰2 小时前
从Vue源码解锁位运算符:提升代码效率的秘诀
前端·javascript·vue.js