前端学习--实现二维码识别功能

概述:

最近所做的毕设项目正好与之前很火的共享单车相关,共享单车应用中很关键的一个部分就是扫码用车,但我之前没有做过相关的模块,在参考网上相关实现的教程时发现,基本上所有的二维码识别模块都是通过客户端来完成的很少有通过前端技术实现。令我很苦恼。

但是功夫不负有心人,查阅过大量资料后我在github上找到了一个用js实现二维码扫描的库(https://github.com/LazarSoft/jsqrcode),而且顺藤摸瓜的找到了采用这个库实现的真实例子(https://webqr.com/)。

功能演示

这里我们的网页只是文件只是放在本地,并使用ubuntu自带的firefox打开,如果使用其他浏览器比如谷歌可能无法弹出请求摄像头的模态框(谷歌的安全策略不允许调用本地媒体)

这里写图片描述

允许摄像头后就会开始捕捉摄像头中的二维码

这里写图片描述

查看扫码结果,我们使用草料二维码(https://cli.im/)生成了里面包含一个“1”字符的二维码,经过我们的二维码识别程序成功识别了出来,并在下面显示出来。

这里写图片描述

程序流程图

这里写图片描述

代码

index.htm(其中引用的js除了webcam.js为自己编写的其他均为githubjsqrcode上下载的js库)

<html>
<head>
  <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
  <meta content="yes" name="apple-mobile-web-app-capable">
  <meta content="black" name="apple-mobile-web-app-status-bar-style">
  <meta content="telephone=no" name="format-detection">
  <meta content="email=no" name="format-detection">
  <script type="text/javascript" src="https://cdn.bootcss.com/jquery/2.0.0/jquery.js"></script>

  <title>scan-code</title>
  <style type="text/css">
    *{
        padding:0;
        margin:0;
    }
    a{
        text-decoration:none;
        color:#fff;
    }
    html{
        width:100%;
        height:100%;
        font-size:16px;
    }
    body{
        width:100%;
        height:100%;

    }
    .total{
        width:100%;
        height:100%;
        /*background:url(/static/img/bg2.jpeg) no-repeat;*/
        background-size:100% 100%;
        overflow: hidden;
        /*background-color: #322F42;*/
    }
    #back_upper{
        display: block;
        width:4rem;
        height:4rem;
        margin-top: 1rem;
        margin-left: 1rem;
        background:url(http://img0.ph.126.net/7vVoDLyELLu5Ti2agzvxjA==/106116066320155563.png) no-repeat;
        opacity:1;
    }
    #v{
        width:320px;
        height:240px;
    }
    #qr-canvas{
        display:none;
    }
    #outdiv
    {

    }
    .scanning_frame{
        margin:5rem auto;
        width:320px;
        height:240px;
        border: 3px solid #000;
        position: relative
    }
    .infor{
        width:15rem;
        height: 4rem;
        text-align: center;
        line-height: 4rem;
        background:#d81e06;
        color: #fff;
        border-radius: 2rem;
        opacity: 0.6;
        margin:0 auto;
    }
    #result{
        width:15rem;
        height:4rem;
        font-size:2rem;
        text-align: center;
        line-height: 4rem;
        margin:0 auto;
        color: #d81e06;
    }
    /*加载动画效果*/
    .spinner {
        width: 60px;
        height: 60px;
        position: absolute;
        top:90px;
        left: 130px;
        /*background-color: #fff;*/
    }

    .double-bounce1, .double-bounce2 {
        width: 100%;
        height: 100%;
        border-radius: 50%;
        background-color: #d81e06;
        opacity: 0.6;
        position: absolute;
        top: 0;
        left: 0;
        -webkit-animation: bounce 2.0s infinite ease-in-out;
        animation: bounce 2.0s infinite ease-in-out;
    }

    .double-bounce2 {
        -webkit-animation-delay: -1.0s;
        animation-delay: -1.0s;
    }

    @-webkit-keyframes bounce {
        0%, 100% { -webkit-transform: scale(0.0) }
        50% { -webkit-transform: scale(1.0) }
    }

    @keyframes bounce {
        0%, 100% {
        transform: scale(0.0);
        -webkit-transform: scale(0.0);
        }
        50% {
        transform: scale(1.0);
        -webkit-transform: scale(1.0);
        }
    }
    </style>
</head>

<body>
    <div class="total">
        <!-- 扫码区域 -->
        <div id="outdiv" class="scanning_frame">
            <video id="v" autoplay></video>
            <canvas id="qr-canvas"></canvas>
            <!--加载动画-->
            <div class="spinner" id="loading">
                <div class="double-bounce1"></div>
                <div class="double-bounce2"></div>
            </div>
        </div>
        <div class="infor">请扫描车上的二维码</div>
        <!-- 展示扫码结果 -->
        <div>
            <p id="result"></p>
        </div>
    </div>

<script type="text/javascript" src="js/grid.js"></script>
<script type="text/javascript" src="js/version.js"></script>
<script type="text/javascript" src="js/detector.js"></script>
<script type="text/javascript" src="js/formatinf.js"></script>
<script type="text/javascript" src="js/errorlevel.js"></script>
<script type="text/javascript" src="js/bitmat.js"></script>
<script type="text/javascript" src="js/datablock.js"></script>
<script type="text/javascript" src="js/bmparser.js"></script>
<script type="text/javascript" src="js/datamask.js"></script>
<script type="text/javascript" src="js/rsdecoder.js"></script>
<script type="text/javascript" src="js/gf256poly.js"></script>
<script type="text/javascript" src="js/gf256.js"></script>
<script type="text/javascript" src="js/decoder.js"></script>
<script type="text/javascript" src="js/qrcode.js"></script>
<script type="text/javascript" src="js/findpat.js"></script>
<script type="text/javascript" src="js/alignpat.js"></script>
<script type="text/javascript" src="js/databr.js"></script>
<script src="js/webcam.js"></script>
<script type="text/javascript">load()</script>
</body>
</html>

webcam.js

var n = null;
var v = null;
var gCtx = null;

function captureToCanvas(){

      try{
            gCtx.drawImage(v,0,0);//在canvas元素中绘出video的某一帧
            try{
                qrcode.decode();//扫描二维码
                //console.log(qrcode.decode());//扫描成功输出二维码的信息
                document.getElementById('loading').style.display = "none";//隐藏掉加载动画
            }
            catch(e){
                console.log(e);//未扫描出二维码,输出错误信息
                setTimeout(captureToCanvas, 500);//500ms之后再重绘canvas
                document.getElementById('loading').style.display = "block";
            }
        }
        catch(e){
                console.log(e);//若失败,输出错误信息
                setTimeout(captureToCanvas, 500);//500ms再重绘canvas
        }
}
//初始化canvas元素,形成一个矩形框
function initCanvas(w,h){

    n = navigator;
    v = document.getElementById("v");
    var gCanvas = document.getElementById("qr-canvas");
    gCanvas.style.width = w + "px";
    gCanvas.style.height = h + "px";
    gCanvas.width = w;
    gCanvas.height = h;
    gCtx = gCanvas.getContext("2d");
    gCtx.clearRect(0, 0, w, h);
}

function setwebcam(){
var options = true;
if(navigator.mediaDevices && navigator.mediaDevices.enumerateDevices)
{
    try{
        navigator.mediaDevices.enumerateDevices().then(function(devices) {
          devices.forEach(function(device) {
            if (device.kind === 'videoinput') {
              if(device.label.toLowerCase().search("back") >-1)
                options={'deviceId': {'exact':device.deviceId}, 'facingMode':'environment'} ;
            }


            console.log(device.kind + ": " + device.label +" id = " + device.deviceId);
          });
          setwebcam2(options);

        });
    }
    catch(e)
    {
        console.log(e);
    }
}
else{
    console.log("no navigator.mediaDevices.enumerateDevices" );

}
}

function setwebcam2(options){

          var p = n.mediaDevices.getUserMedia({video: options, audio: false});
          p.then(success, error);
        //  setTimeout(captureToCanvas, 500);

}
function success(stream){
    v.srcObject = stream;
    setTimeout(captureToCanvas(), 500);
}
function error(error){
    console.log(error);
}
function load(){
    initCanvas(800,600);
    qrcode.callback = read;
    setwebcam();
}
function read(a){
    document.getElementById("result").innerHTML = a.toString();
    console.log("qrcode info:"+a);//输出扫描后的信息
}

版权声明:本文为No_red原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。