`
it疯子
  • 浏览: 8553 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

HTML 5 手机扫描二维码登陆网页

阅读更多
    首先声明我不是专业做前端的,只是一个java开发者,最近要做一个手机版的网站,但是需求要做类似于微信,扫描网页上的二维码登陆网页版微信,以当时认为这东西必须要APP才能支持,因为所有扫描二维码都是必须在手机上安装APP ,也看过phonegap,其实也是需要生成一个apk,需要用户安装。所以就是硬着头皮在网上找资料。最后终于看到说HTML5可以调用视频,灵光一现。继续搜索。这时候才发现原来HTML5原来真的可以实现,
    我先介绍一下它的大概处理流程(个人理解),其实大概思路就是通过调用手机端的摄像头将视频放入video中,然后将视频中的某一帧放入canvas中,canvas将图片信息转换换成base64码,把base64码传到后台转换成数据流,用java解析就行了。
    下面就上代码了(调试的时候才发现手机浏览器中只有欧朋浏览器支持,而且版本是opera classic的才行):
1、首先就是页面了

<!DOCTYPE HTML >
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>扫描二维码</title>
<script type="text/javascript" >
var video,canvas;

window.addEventListener('DOMContentLoaded',function(){
'use strict';

//调取摄像头
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

if (navigator.getUserMedia) {
navigator.getUserMedia({video: true}, gotStream, noStream);

video = $("#video").get(0);
canvas = $("#canvas").get(0);

//启动摄像头成功之后开始获取二维码
scanCode();

} else {
console.log('Native web camera streaming (getUserMedia) not supported in this browser.');
}

//调取摄像头成功的回调函数
function gotStream(stream) {
  if (video.mozSrcObject !== undefined) {
video.mozSrcObject = stream;
} else {
video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
}
video.play();
  }
 
  //调取摄像头失败的回调函数
  function noStream() {
  console.error('An error occurred: [CODE ' + error.code + ']');
  }


$("#myVideo").bind("play", function () {
//$("#photo").attr("disabled",false);
    });

},false);


//抓取video画面放入canvas
function photograph(){
var context = canvas.getContext("2d");

//获取抓取图片的区域

//获取取景框其实坐标位置和宽高
var cameraAperture_X = $("#td1").width();
//var cameraAperture_Y = $("#mid_div").height();
var cameraAperture_Y = $("#table_h").offset().top - $(".smtwo").height();
var cameraAperture_W = $("#cameraAperture").width();
var cameraAperture_H = $("#cameraAperture").height();

context.drawImage(video, Math.round(cameraAperture_X/2), Math.round(cameraAperture_Y/2),cameraAperture_W, cameraAperture_H,0,0,cameraAperture_W,cameraAperture_H);
   
    imageConvertToGray(context);
   
var imgData =canvas.toDataURL("image/png");

$("#code").val(imgData);

}

//将图片处理成黑白的(二维码扫描需要处理黑白色图片,如果仅用于拍照这一步就省略了)
function imageConvertToGray(ctx){
var length = canvas.width * canvas.height;
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (var i = 0; i < length * 4; i += 4) {
var myRed = imageData.data[i];
var myGreen = imageData.data[i + 1];
var myBlue = imageData.data[i + 2];
myGray = parseInt((myRed + myGreen + myBlue) / 3);
imageData.data[i] = myGray;
imageData.data[i + 1] = myGray;
imageData.data[i + 2] = myGray;
}

ctx.putImageData(imageData, 0, 0);
  }



function scanCode(){
//生成图片的base64码
photograph();

$("#picForm").ajaxSubmit({
url:'${ctx}/xxxx/xxxx.htm',
type:'post',
dataType:'text',
success:function(data){
if(data != ""){//扫描出结果
window.location.href="${ctx}/xxxx/xxxxxxxxxx.htm?data="+data+"&status="+$("#status").val();
//alert("扫描信息为:"+data);
}else{//继续扫描

setTimeout(function(){
scanCode();
},2000);
}
}

  });

}

</script>
</head>
<body>
<form id="picForm" action="${ctx}/xxxx/xxxx.htm" method="post" >
<input type="hidden" value="" id="code" name="code"/>
<input type="hidden" value="${status }" id="status" name="status"/>
<section class="smtwo">
<h1><a class="back" href="${ctx }/index/index.htm"><img src="${ctx }/images/smtwo_1.png" style="border:none" alt=""></a>${titleMsg }</h1>
</section>
<section style="position: relative;">
<video  width="100%" id="video" autoplay="autoplay" onclick="photograph();"></video>
<canvas width="200" height="200" id="canvas" style="display: none;"></canvas>
<div style="position: absolute;top: 0;left: 0;">
<div class="smtw_bg butsmtw" id="mid_div">

${content }

</div>
<table width="100%" border="0" cellpadding="0" cellspacing="0" id="table_h">
<tr>
<td class="smtw_bg td1" id="td1"></td>
<td class="td2">
<div class="smtw_td" style="width:200px;height:200px;" id="cameraAperture" onclick="photograph()">
<span class="br1"></span>
<span class="br2"></span>
<span class="br3"></span>
<span class="br4"></span>
</div>
</td>
<td class="smtw_bg td1"></td>
</tr>
</table>
<div class="smtw_bg butsmtw" id="bottom_div">

</div>
</div>
</section>  
</form>
</body>
</html>


页面说明:
window.addEventListener 页面启动的时候调用摄像头,我试过不用这个直接$(document).ready();不好使。
imageConvertToGray():这个函数主要是把照片变成黑白的,这个很重要,因为取得一帧图片是彩色的话就会影响读取二维码的效果(反正我没有处理成黑白之前扫描没成功过)
scanCode():这个就是扫描了,2秒抓一张图片传到后台进行处理如果成功会返回二维码包含内容。
    这里需要说明的是canvas.toDataURL("image/png");canva转换成base64必须放到input隐藏变量里面,因为这个字符串很长。不能通过url提交,这样这个字符串长度会超了。

    下面着中说取景框的问题,因为微信扫描二维码界面会有一个取景框,所以我们也要模拟这个,也就是说 在video中 的某一个区域截取图片放到canvas里面,所以在photograph()函数里面,我在context.drawImage的时候计算了需要取景的坐标,关于这个参数大家可以查看canvas属性就可以了解。
    下来就是后台java解析了百度一下,到处都是,下面是我用的,置于jar包,大家自己找找哈。
package sy.util;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;

import javax.imageio.ImageIO;

import jp.sourceforge.qrcode.QRCodeDecoder;
import sy.bean.TwoDimensionCodeImage;
import Decoder.BASE64Decoder;

public class QRCodeDecoderHandlerUtil {

/**
* 解析二维码(QRCode)
* @param input 输入流
* @return
*/
  public static String decoderQRCode(InputStream input) throws Exception{ 
          BufferedImage bufImg = null; 
          String content = null;
         
          bufImg = ImageIO.read(input); 
          QRCodeDecoder decoder = new QRCodeDecoder(); 
          content = new String(decoder.decode(new TwoDimensionCodeImage(bufImg)), "utf-8");
         
          return content; 
      }
 
  /**
   * 解析二维码(QRCode)
   * @param imgPath 图片路径
   * @return
   */
      public static String decoderQRCode(String imgPath) throws Exception{ 
          // QRCode 二维码图片的文件 
          File imageFile = new File(imgPath); 
          BufferedImage bufImg = null; 
          String content = null;
         
          bufImg = ImageIO.read(imageFile); 
          QRCodeDecoder decoder = new QRCodeDecoder(); 
          content = new String(decoder.decode(new TwoDimensionCodeImage(bufImg)), "utf-8"); 
         
          return content; 
      } 

      /**
       * 解析二维码
       * @param imgStr 图片的Base64信息
       * @return
       */
      public static String decoderQRCodeForBase64(String imgStr) throws Exception{
      if (imgStr == null){
      return "";
      }
     
      BASE64Decoder decoder = new BASE64Decoder();
     
          byte[] b = decoder.decodeBuffer(imgStr);
          for(int i=0;i<b.length;++i){
              if(b[i]<0){//调整异常数据
                  b[i]+=256;
              }
          }
         
          InputStream input = new ByteArrayInputStream(b);
         
          String content = decoderQRCode(input);
         
          return content;
             
     
      }
     
      public static void main(String[] args) {
}

}

说明:我是借用decoderQRCode(InputStream input)方法,因为考虑到,如果用decoderQRCode(String imgPath) 就需要在服务器生成临时图片,这样不仅繁琐,还会产生一些垃圾图片。
decoderQRCodeForBase64这个方法就是将base64(前台取过来的)变成InputStream 然后交给decoderQRCode(InputStream input)处理

好了OK ,置于 网页端的二维码里面如何存放信息,这个我想大家根据业务了,具体流程就是手机扫描到二维码里面的信息之后,手机版服务器通知网页版服务器然后网页版服务器登陆并且跳转到相应页面就OK了

第一次发帖,如果说的不明白的还请谅解,如果需要更详细的了解,请加我的QQ号:514772731
0
0
分享到:
评论
1 楼 lgb020 2015-09-07  
能发份源码给我嘛?谢谢.邮箱:lgb934@163.com

相关推荐

    通过扫描二维码打开app的实现代码

    最近有朋友问小编这样一个问题,先给大家说下项目需求:扫描二维码打开app如果用户没有这个app则提示它跳转。 用网页直接来调用app是不打可能的,必须原生那边先做一些配置。 首先,安卓和苹果的调用方法是不同的。 ...

    python京东抢购二维码登录实现

    201 : 二维码未扫描 ,请扫描二维码 201 : 二维码未扫描 ,请扫描二维码 201 : 二维码未扫描 ,请扫描二维码 202 : 请手机客户端确认登录 200 : BADACIFYhf6fakfHvjiYTlwGzSp4EjFATN3Xw1ePR1hITtw0 登陆成功 +++++++...

    H5外部浏览器直接调起微信手机网站调用微信分享

    H5外部浏览器直接调起微信 tml5手机网站调用微信分享,其中示例包括 1. 获取网络类型 2. 调起客户端的图片播放组件 3. 调用微信扫描二维码 4. 判断是否安装对应的应用 5. 发送邮件 6. 分享到微信朋友圈

    PHPCMS V9.6.6 修改版

    5. 验证码修改 6. 支持H5上传,移除Flash上传 7. 修改后台缩略图裁切图片,移除Flash裁切改为H5裁切 8. 后台附件上传修改为H5上传,会员头像上传修改为H5上传 9. 修改后台界面,修改后台登录界面、后台锁屏界面、...

    PHPCMS V9.6.6 修改版#资源达人分享计划#

    5. 验证码修改 6. 支持H5上传,移除Flash上传 7. 修改后台缩略图裁切图片,移除Flash裁切改为H5裁切 8. 后台附件上传修改为H5上传,会员头像上传修改为H5上传 9. 修改后台界面,修改后台登录界面、后台锁屏界面、...

Global site tag (gtag.js) - Google Analytics