html5移动端页面上调用手机摄像头扫描二维码并获取二维码信息代码?

发布网友 发布时间:2022-04-25 02:38

我来回答

3个回答

懂视网 时间:2022-05-12 04:09

本篇文章给大家带来的内容是关于用exfe.js和canvas解决移动端 IOS 拍照上传图片翻转问题,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

记得我初入前端差不多一年,公司做了一个webapp,有上传头像功能,当时这个项目不是我在负责,测试的时候发现苹果用户拍照上传头像会翻转,当时几个前端的同学捯饬了一下午也没解决,结果问题转到我这里,还有半个小时下班;当时也是一脸懵逼,首先想到的是,这怎么判断它是否翻转了呢?安卓没问题啊,有些苹果手机相册里面的图片也没问题啊,js能有这种功能判断吗?上网查资料,果不其然,有!那就是exfe.js,继续研究,此时组长姐姐已经买好晚餐,老板也来慰问,最后弄到晚上9点多,算是解决了。

时隔两年,昨天又遇到这个问题,已经离开上家公司一年半了,现公司做一个万圣节活动,里面也是上传图片,合成鬼脸图,早早两天前已经做好发给项目经理(我们这边是远程,少许几个开发者),晚上快下班时,项目经理发消息“ios图片翻转,解决一下,今晚要上线,加个班”,心里一万个草泥马奔腾而过,1是我忘了ios有这个问题,2是已经发给你2天了,你快下班的时候跟我说有问题,加个班!我晚上安排要推掉!还是无偿!没有慰问餐,也没有歉意,还是很好意思的加个班,还是苦笑一声回复,“好吧,下次提前测一下”,这回毕竟遇见过,处理起来比较快,7点多搞定。后续又有什么部署的问题,不是我的问题了,又是快9点了。

只是几乎类似的场景,感慨一下。

上代码

html部分

<input type="file" accept="image/*" id="uploadImage" capture="camera" onchange="selectFileImage(this);" />
<img alt="preview" src="" id="myImage"/>

exfe.js来读取图片信息,我们上传的图片里面是有很多信息的

//获取照片方向角属性,用户旋转控制
EXIF.getData(file, function() {
 EXIF.getAllTags(this);
 Orientation = EXIF.getTag(this, 'Orientation');
 console.log(Orientation);
});

Orientation的值有1,3,6,8之类的,分别代表0°,180°,顺时针90°,逆时针90°

当我们知道了图片的旋转角度,我们就可以用canvas来处理他们了,最后得到我们想要的结果,这里摘抄了网上一段代码,如果有特殊功能,那就要自己写一些逻辑了,也就是判断角度,判断操作系统,然后用canvas重新绘制,生成base,最后对dom的操作,显示图片。

上代码

function selectFileImage(fileObj) {
 var file = fileObj.files['0'];
 //图片方向角 
 var Orientation = null;
 if (file) {
  //获取照片方向角属性,用户旋转控制
  EXIF.getData(file, function() {
  EXIF.getAllTags(this);
  Orientation = EXIF.getTag(this, 'Orientation');
  console.log(Orientation)
  });
  var oReader = new FileReader();
  oReader.onload = function(e) {
  var image = new Image();
  image.src = e.target.result;
  image.onload = function() {
   var expectWidth = this.naturalWidth;
   var expectHeight = this.naturalHeight;

   if (this.naturalWidth > this.naturalHeight && this.naturalWidth > 800) {
   expectWidth = 800;
   expectHeight = expectWidth * this.naturalHeight / this.naturalWidth;
   } else if (this.naturalHeight > this.naturalWidth && this.naturalHeight > 1200) {
   expectHeight = 1200;
   expectWidth = expectHeight * this.naturalWidth / this.naturalHeight;
   }
   var canvas = document.createElement("canvas");
   var ctx = canvas.getContext("2d");
   canvas.width = expectWidth;
   canvas.height = expectHeight;
   ctx.drawImage(this, 0, 0, expectWidth, expectHeight);
   var base = null;
   //修复ios
   if (navigator.userAgent.match(/iphone/i)) {
   console.log('iphone');
   //如果方向角不为1,都需要进行旋转 
   if(Orientation != "" && Orientation != 1){
    alert('旋转处理');
    switch(Orientation){
    case 6://需要顺时针(向左)90度旋转
     rotateImg(this,'left',canvas);
     break;
    case 8://需要逆时针(向右)90度旋转
     rotateImg(this,'right',canvas);
     break;
    case 3://需要180度旋转
     rotateImg(this,'right',canvas);//转两次
     rotateImg(this,'right',canvas);
     break;
    }
   }
   base = canvas.toDataURL("image/jpeg", 1);
   }else if (navigator.userAgent.match(/Android/i)) {// 修复android
   var encoder = new JPEGEncoder();
   base = encoder.encode(ctx.getImageData(0, 0, expectWidth, expectHeight), 80);
   }else{
   if(Orientation != "" && Orientation != 1){
    switch(Orientation){
    case 6://需要顺时针(向左)90度旋转
     rotateImg(this,'left',canvas);
     break;
    case 8://需要逆时针(向右)90度旋转
     rotateImg(this,'right',canvas);
     break;
    case 3://需要180度旋转
     rotateImg(this,'right',canvas);//转两次
     rotateImg(this,'right',canvas);
     break;
    }
   }

   base = canvas.toDataURL("image/jpeg", 1);
   }
   $("#myImage").attr("src", base);
  };
  };
  oReader.readAsDataURL(file);
 }
 }

 //对图片旋转处理 
 function rotateImg(img, direction,canvas) {
 //最小与最大旋转方向,图片旋转4次后回到原方向
 var min_step = 0;
 var max_step = 3;
 if (img == null)return;
 //img的高度和宽度不能在img元素隐藏后获取,否则会出错
 var height = img.height;
 var width = img.width;
 //var step = img.getAttribute('step');
 var step = 2;
 if (step == null) {
  step = min_step;
 }
 if (direction == 'right') {
  step++;
  //旋转到原位置,即超过最大值
  step > max_step && (step = min_step);
 } else {
  step--;
  step < min_step && (step = max_step);
 }
 //旋转角度以弧度值为参数
 var degree = step * 90 * Math.PI / 180;
 var ctx = canvas.getContext('2d');
 switch (step) {
  case 0:
  canvas.width = width;
  canvas.height = height;
  ctx.drawImage(img, 0, 0);
  break;
  case 1:
  canvas.width = height;
  canvas.height = width;
  ctx.rotate(degree);
  ctx.drawImage(img, 0, -height);
  break;
  case 2:
  canvas.width = width;
  canvas.height = height;
  ctx.rotate(degree);
  ctx.drawImage(img, -width, -height);
  break;
  case 3:
  canvas.width = height;
  canvas.height = width;
  ctx.rotate(degree);
  ctx.drawImage(img, -width, 0);
  break;
 }
 }

热心网友 时间:2022-05-12 01:17

html5移动端调用手机摄像头扫描二维码并获取二维码信息代码如下:

[html] view plain copy

<!DOCTYPE html>  

<html><head>  

<title>HTML5 code Reader</title>  

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">  

</head>  

<style type="text/css">  

html, body { height: 100%; width: 100%; text-align:center; }    

</style>  

<script src="jquery-1.9.1.js"></script>  

<script>  

//这段代 主要是获取摄像头的视频流并显示在Video 签中    

var canvas=null,context=null,video=null;     

window.addEventListener("DOMContentLoaded", function ()  

{  

try{  

canvas = document.getElementById("canvas");  

context = canvas.getContext("2d");  

video = document.getElementById("video");  

var videoObj = { "video": true,audio:false},  

flag=true,  

MediaErr = function (error)  

{             

flag=false;    

if (error.PERMISSION_DENIED)  

{  

alert('用户拒绝了浏览器请求媒体的权限', '提示');  

} else if (error.NOT_SUPPORTED_ERROR) {  

alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器', '提示');  

} else if (error.MANDATORY_UNSATISFIED_ERROR) {  

alert('指定的媒体类型未接收到媒体流', '提示');  

} else {  

alert('系统未能获取到摄像头,请确保摄像头已正确安装。或尝试刷新页面,重试', '提示');  

}  

};  

//获取媒体的兼容代码,目前只支持(Firefox,Chrome,Opera)  

if (navigator.getUserMedia)  

{  

//qq浏览器不支持  

if (navigator.userAgent.indexOf('MQQBrowser') > -1) {  

alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器', '提示');  

return false;  

}  

navigator.getUserMedia(videoObj, function (stream) {  

video.src = stream;                  

video.play();        

}, MediaErr);             

}  

else if(navigator.webkitGetUserMedia)  

{  

navigator.webkitGetUserMedia(videoObj, function (stream)  

{            

video.src = window.webkitURL.createObjectURL(stream);             

video.play();             

}, MediaErr);             

}  

else if (navigator.mozGetUserMedia)  

{  

navigator.mozGetUserMedia(videoObj, function (stream) {  

video.src = window.URL.createObjectURL(stream);  

video.play();  

}, MediaErr);  

}  

else if (navigator.msGetUserMedia)  

{   

navigator.msGetUserMedia(videoObj, function (stream) {  

$(document).scrollTop($(window).height());  

video.src = window.URL.createObjectURL(stream);  

video.play();  

}, MediaErr);  

}else{  

alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器');  

return false;  

}  

if(flag){  

alert('为了获得更准确的测试结果,请尽量将二维码置于框中,然后进行拍摄、扫描。 请确保浏览器有权限使用摄像功能');  

}  

//这个是拍照按钮的事件,            

$("#snap").click(function () {startPat();}).show();  

}catch(e){        

printHtml("浏览器不支持HTML5 CANVAS");         

}   

}, false);  

//打印内容到页面        

function printHtml(content){  

$(window.document.body).append(content+"<br/>");  

}  

//开始拍照  

function startPat(){  

setTimeout(function(){//防止调用过快  

if(context)  

{  

context.drawImage(video, 0, 0, 320, 320);       

CatchCode();   

}  

},200);  

}   

//抓屏获取图像流,并上传到服务器        

function CatchCode() {          

if(canvas!=null)  

{    

//以下开始编 数据     

var imgData = canvas.toDataURL();   

//将图像转换为base数据  

var baseData = imgData;//.substr(22); //在前端截取22位之后的字符串作为图像数据  

//开始异步上  

$.post("saveimg.php", { "img": baseData },function (result)  

{     

printHtml("解析结果:"+result.data);  

if (result.status == "success" && result.data!="")  

{                   

printHtml("解析结果成功!");  

}else{    

startPat();//如果没有解析出来则重新抓拍解析         

}  

},"json");  

}  

}        

</script>  

<body>  

<div id="support"></div>  

<div id="contentHolder">         

<video id="video" width="320" height="320" autoplay>  

</video>         

<canvas style="display:none; background-color:#F00;" id="canvas" width="320" height="320">  

</canvas> <br/>  

<button id="snap" style="display:none; height:50px; width:120px;">开始扫描</button>    

</div>  

</body></html>  

热心网友 时间:2022-05-12 02:35

首先感谢 jsqrcode 的开发者,提供这么优秀的解析二维码的代码,为我减少了很大的工作量。jsqrcode 地址 百度
我的代码库地址百度
1.解决的问题:
1.能够在微博客户端呼起摄像头扫描二维码并且解析;
2.能够在原生浏览器和微信客户端中扫描二维码并且解析;
2.优点:
web端或者是 h5端可以直接完成扫码的工作;
3.缺点:
图片不清晰很容易解析失败(拍照扫描图片需要镜头离二维码的距离很近),相对于 native 呼起的摄像头解析会有1-2秒的延时。
说明:
此插件需要配合zepto.js 或者 jQuery.js使用
使用方法:
1.在需要使用的页面按照下面顺序引入lib目录下的 js 文件

复制代码
代码如下:

<script src="lib/zepto.js"></script>
<script src="lib/qrcode.lib.min.js"></script>
<script src="lib/qrcode.js"></script>

2.自定义按钮的 html 样式
因为该插件需要使用<input type="file" /> ,该 html 结构在网页上面是有固定的显示样式,为了能够自定义按钮样式,我们可以按照下面的示例代码结构嵌套代码

复制代码
代码如下:

<div class="qr-btn" node-type="jsbridge">扫描二维码1
<input node-type="jsbridge" type="file" name="myPhoto" value="扫描二维码1" />
</div>

然后设置 input 按钮的 css 隐藏按钮,比如我使用的是属性选择器

复制代码
代码如下:

input[node-type=jsbridge]{
visibility: hidden;
}

这里我们只需要按照自己的需要定义class="qr-btn"的样式即可。
3.在页面上初始化 Qrcode 对象

复制代码
代码如下:

//初始化扫描二维码按钮,传入自定义的 node-type 属性
$(function() {
Qrcode.init($('[node-type=jsbridge]'));
});

主要代码解析

复制代码
代码如下:

(function($) {
var Qrcode = function(tempBtn) {
//该对象只支持微博域下的解析,也就是说不是微博域下的页面只能用第二种方案解析二维码
if (window.WeiboJSBridge) {
$(tempBtn).on('click', this.weiBoBridge);
} else {
$(tempBtn).on('change', this.getImgFile);
}
};
Qrcode.prototype = {
weiBoBridge: function() {
WeiboJSBridge.invoke('scanQRCode', null, function(params) {
//得到扫码的结果
location.href=params.result;
});
},
getImgFile: function() {
var _this_ = this;
var imgFile = $(this)[0].files;
var oFile = imgFile[0];
var oFReader = new FileReader();
var rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowmp)$/i;
if (imgFile.length === 0) {
return;
}
if (!rFilter.test(oFile.type)) {
alert("选择正确的图片格式!");
return;
}
//读取图片成功后执行的代码
oFReader.onload = function(oFREvent) {
qrcode.decode(oFREvent.target.result);
qrcode.callback = function(data) {
//得到扫码的结果
location.href = data;
};
};
oFReader.readAsDataURL(oFile);
},
destory: function() {
$(tempBtn).off('click');
}
};
//初始化
Qrcode.init = function(tempBtn) {
var _this_ = this;
var inputDom;
tempBtn.each(function() {
new _this_($(this));
});
$('[node-type=qr-btn]').on('click', function() {
$(this).find('[node-type=jsbridge]')[0].click();
});
};
window.Qrcode = Qrcode;
})(window.Zepto ? Zepto : jQuery);

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com