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:[email protected]
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/[email protected]/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已经编写好了。

源代码

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

相关推荐
JiangJiang5 分钟前
🚀 Vue人看React useRef:它不只是替代 ref
javascript·react.js·面试
1024小神10 分钟前
在GitHub action中使用添加项目中配置文件的值为环境变量
前端·javascript
龙骑utr14 分钟前
qiankun微应用动态设置静态资源访问路径
javascript
Jasmin Tin Wei15 分钟前
css易混淆的知识点
开发语言·javascript·ecmascript
齐尹秦18 分钟前
CSS 列表样式学习笔记
前端
wsz777722 分钟前
js封装系列(一)
javascript
Mnxj22 分钟前
渐变边框设计
前端
用户76787977373225 分钟前
由Umi升级到Next方案
前端·next.js
快乐的小前端26 分钟前
TypeScript基础一
前端
北凉温华27 分钟前
UniApp项目中的多服务环境配置与跨域代理实现
前端