很实用的h5实现名片扫描识功能快速结合市场运营
功能描述:
点击名片识别按钮,将名片上的个人信息扫描并解析出来显示。
实现步骤:
1.点击第一个页面上的名片识别按钮,调出手机摄像头和相册,让用户进行选择
2.获取照片或者图片的base64数据,传值到第二个页面
3.在第二个页面接受参数,调取第三方的orc接口进行图片解析,得到名片上的个人信息,并显示。
豌豆资源搜索网站https://55wd.com
代码:
第一个页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> html { font-size: 62.5%; /*10 ÷ 16 × 100% = 62.5%*/ } #btn, #input_file { font-size: 4.0rem; /*2.4*10px=24px*/ } #input_file { position: absolute; /*相对于最近的祖先元素定位,如果absolute的元素,没有被positioned的祖先元素,那么他是相对于文档的body元素来定位的;一个“positioned”元素是指 position 值不是 static 的元素*/ left: 8px; opacity: 0; z-index: 10; } #btn { position: absolute; z-index: 0; color: black; } </style> <script type="text/javascript"> //步骤2 function setImagePreview() { var docObj = document.getElementById("input_file"); var imgObjPreview = document.getElementById("myimg"); var reader = new FileReader(); reader.readAsDataURL(docObj.files[0]); reader.onload = function (e) { var dataobj = this.result; imgObjPreview.src = dataobj; imgObjPreview.onload=function(){ var cropStr =compress(imgObjPreview,800,800,1.0); console.log("cropStr:" + cropStr);//压缩后的base64 带前缀的 var dot = cropStr.indexOf(","); var newBase64Data = cropStr.substring(dot + 1, cropStr.length); //console.log("newBase64Data:"+newBase64Data); localStorage.setItem("base64data", newBase64Data); //步骤3 jump(); } } } /* * 图片压缩 * img 原始图片 * width 压缩后的宽度 * height 压缩后的高度 * ratio 压缩比率 */ function compress(img, width, height, ratio) { var canvas, ctx, img64; canvas = document.getElementById('canv'); canvas.width = width; canvas.height = height; ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, width, height);//把图片绘制到画布上 img64 = canvas.toDataURL("image/jpeg", ratio); return img64; } function jump() { //window.setTimeout("window.location.href='cardRecognition.html'", 5000); var file = document.getElementById("input_file"); // for IE, Opera, Safari, Chrome if (file.outerHTML) { file.outerHTML = file.outerHTML; } else { // FF(包括3.5) file.value = ""; } window.location.href = "cardRecognition.html"; } </script> </head> <body> <div><!--步骤1--> <input type="button" value="名片识别" id="btn" disabled="disabled" /> <input type="file" accept="image/*" multiple="multiple" id="input_file" onchange="setImagePreview()" /> <input type="hidden" id="img" name="img" value="" /> </div> <div> <canvas id="canv" width="400" height="400" style="border:1px solid red;"></canvas> <img id="myimg" src="" alt="预览" width="400" height="400" /> </div> </body> </html>
第二个页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>名片识别</title> <link rel="stylesheet" type="text/css" href="../css/loader.min.css"> <script src="../js/jquery-3.2.1.min.js"></script> <style type="text/css"> </style> <script type="text/javascript"> $(function () { var key = "Fna5PKtWYEGE3uCkyZvoMy"; var secret = "1cc17342718546f9a535a15eb243c87a"; var typeId = 20; var format = "json"; var base64Data = localStorage.getItem("base64data"); //var test=localStorage.getItem("test"); localStorage.clear(); //console.log(base64Data); //alert(base64Data); //alert(test); requestData(); ///////////调取翔云orc接口////////// function requestData() { var oData = { "img": base64Data, "key": key, "secret": secret, "typeId": typeId, "format": format }; $.ajax({ url: "https://www.netocr.com/api/recogliu.do", //url:"http://101.200.79.184/api/recogliu.do", type: 'POST', dataType: "json",//注意,此处设置为text,可以在ie中解析返回的xml data: oData, success: function (returndata) { if (returndata != null) { var jsonresult = JSON.stringify(returndata); var mdata = $.parseJSON(jsonresult); console.log(mdata); var len = mdata.cardsinfo[0].items.length; for (var i = 0; i <= len - 1; i++) { item = mdata.cardsinfo[0].items[i]; $("#tb").append("<tr></tr><td style=\"border: 1px solid #000;width: 100px\">" + item.desc + "</td>" + "<td style=\"border: 1px solid #000;width: 300px\">" + item.content + "</td></tr>"); } //移除loading $('body').addClass('loaded'); $('#loader-wrapper .load_title').remove(); } }, error: function (returndata) { alert("请求失败"); } }); } }); </script> </head> <body> <div id="loader-wrapper"> <!--loading--> <div id="loader"></div> <div class="loader-section section-left"></div> <div class="loader-section section-right"></div> <div class="load_title">正在识别名片 <br> </div> </div> <div id="dv" align="center"> <table id="tb" style="text-align: center;"> </table> </div> </body> </html>
开发时遇到的问题
1.华为手机自带浏览器无法打开摄像头:
打开手机摄像头或者相册使用的h5的input标签,设置accept="image/*" multiple="multiple" 属性,无法打开摄像头,百度了好多也没有找到解决方案,最后考虑到用户习惯,用户很少用手机自带浏览器,下载了谷歌浏览器和uc浏览器进行测试,没有问题,可以正常打开手机摄像头和相册;
2.使用H5的input type=file标签,会自带样式:
通过修改它的样式,主要是将其透明图设置成0,将其隐藏掉,自己再写个input type=button的按钮覆盖到上面,看起来就是只点击按钮了。
3.点击拍摄或者相册选取图片,获取base64数据,base64数据太长,无法解析。
一开始在电脑的谷歌浏览器进行测试,直接选取的网络上的图片,传图片的base64可以正常解析,但是放到手机上,通过拍摄获取到的图片转成base64数据会很大(5M),我看了下是直接传图(80k)的64倍,可能随图片大小不同,这个数据有差别,后来打算使用压缩后的图片转base64来进行解析,压缩后的base64再转成图是一片黑,压缩失败。后来回来看了下压缩代码,压缩过程是这样的:
/*摄像头方向控制*/ /* * 图片压缩 * img 原始图片 * width 压缩后的宽度 * height 压缩后的高度 * ratio 压缩比率 */ function compress(img, width, height, ratio) { var canvas, ctx, img64; canvas = document.getElementById('canv'); canvas.width = width; canvas.height = height; ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, width, height); //把压缩后的图片绘制到画布上 img64 = canvas.toDataURL("image/jpeg", ratio); return img64; }
这个方法本身是没有问题的,但是放到代码中会有问题,问题出在ctx.drawImage(img, 0, 0, width, height);这句上,img一直无法绘制到画布上,原来是img.src 还没有加载完就开始绘制肯定绘制不上,所以调用img.onload,等到img加载完成后再进行绘制就可以了,最后正确获得压缩后的图片的base64数据。
ok,以上就是一个简单的总结,记录一下。