vue 扫码,vue调用摄像头扫码

  vue 扫码,vue调用摄像头扫码

  主要介绍了通过使用基于vue技术栈的前端开发技术,在浏览器端设置摄像头,进行扫码识别功能,对识别出的二维码进行跳过或其他处理。和对vue浏览器扫码功能的代码感兴趣的朋友一起看看吧。

  

背景

  前不久做了获取浏览器摄像头和扫码识别的功能。在本文中,我整理了知识点和具体代码实现,并将其编译成本文的内容。

  本文主要介绍了通过使用基于vue技术栈的前端开发技术,在浏览器端设置摄像头,进行扫码识别功能,使识别出的二维码可以跳过或进行其他操作。本文由背景介绍、实施效果、技术介绍、代码实现和总结组成。

  

实现效果

  在这个例子中,有两个主页面,第一个页面和代码扫描页面。具体实现效果如下图所示。

  首页:点击扫描二维码按钮,进入扫码页面。

  扫码页面:第一次进入,或者弹出获取摄像头访问权限的系统提示框,点击允许访问,页面开始加载摄像头数据,开始抓取和拾取二维码。如果捕捉到二维码,则开始分析二维码,分析成功后会加载识别成功的弹窗。

  在线体验:https://dragonir.github.io/h5-scan-qrcode

  提示:您需要在带有照相设备的浏览器中垂直访问它。手机屏幕检测的知识可以在我的另一篇文章《五十音小游戏中的前端知识》中找到。

  

技术简介

  

WebRTC API

  WebRTC(Web Real-Time communication s)是一种实时通信技术,它允许网络应用程序或站点在浏览器之间建立对等连接,而无需借助中间媒体,实现视频流和/或音频流或其他任意数据的传输。WebRTC中包含的这些标准使用户无需安装任何插件或第三方软件就可以创建对等数据共享和电话会议。

  三个主要界面:

  MediaStream:可以通过设备的摄像头和麦克风获得视频和音频的同步流。

  RTCPeerConnection:它是WebRTC用来在点对点之间建立稳定高效的流传输的组件。

  RTCDataChannel:它使浏览器能够建立一个高吞吐量、低延迟的通道来传输任意数据。

  去MDN深入学习:WebRTC_API

  

WebRTC adapter

  虽然WebRTC规范已经比较健全和稳定,但并不是所有的浏览器都实现了它的全部功能,有些浏览器需要在部分或全部WebRTC API上添加前缀才能正常使用。

  WebRTC组织在github上提供了一个WebRTC适配器,解决了在不同浏览器上实现WebRTC的兼容性问题。这个适配器是一个JavaScript shim,它允许您根据WebRTC规范编写代码,而不必在所有支持WebRTC的浏览器中编写前缀或其他兼容性解决方案。

  到MDN进行深入研究:WebRTC适配器

  核心的API navigator . media devices . getuser media

  调用网络摄像机需要调用getUserMedia API。MediaDevices.getUserMedia()将提示用户给予使用媒体输入的许可,这将生成包含所请求的媒体类型的轨道的媒体流。此流可能包含视频轨道(来自硬件或虚拟视频源,如摄像机、视频捕获设备和屏幕共享服务等。)、音轨(也来自硬件或虚拟音频源,例如麦克风、A/D转换器等。),或其他轨道类型。

  它返回一个Promise对象,成功后会解析并回调一个MediaStream对象;如果用户拒绝使用权,或者所需的媒体源不可用,promise将拒绝并回调PermissionDeniedError或NotFoundError。(返回的承诺对象可能既不会解决也不会拒绝,因为用户不必选择允许或拒绝。)

  您通常可以使用navigator.mediaDevices来获取媒体设备,例如:

  navigator . media devices . getuser media(约束)。然后(函数(流){

  //使用此流

  })。catch(函数(错误){

  //处理错误

  })

  去MDN深入学习:navigator . media devices . getuser media。

  二维码分析库JSQR

  JsQR是一个纯JavaScript的二维码分析库,读取原始图像或摄像头,定位、提取并分析其中的任意二维码。

  如果要用jsQR扫描网络摄像头流,需要从视频流中提取ImageData,然后可以传递给jsQR。

  JsQR派生了一个方法,该方法接受四个参数,即解码图像数据、宽度、高度和可选对象,以进一步配置扫描行为。

  ImageData:uint 8 clampedarray(8位无符号整数固定数组)的rgba像素值,格式为[r0,g0,b0,a0,r1,g1,b1,a1,].

  const code=jsQR(imageData,width,height,options);

  如果(代码){

  Console.log(找到二维码!,代码);

  }

  去github了解更多关于:jsQR

  

代码实现

  

流程

  整个扫码过程如下图所示:页面初始化,先检查浏览器是否支持mediaDevices的相关API,然后浏览器会调用关闭摄像头,如果调用失败,会执行失败回调;呼叫成功,抓拍视频流,然后扫码识别。如果没有扫描到可识别的二维码,继续扫描。扫码成功后,画一个成功的扫描图案,进行一次成功的回调。

  以下内容拆分流程分别实现相应的功能。

  扫描代码组件扫描器

  

页面结构

  我们先来看看页面结构,主要由四部分组成:

  提示框。

  扫描代码帧。

  视频:显示摄像头捕捉到的视频流。

  画布:绘制二维码识别的视频帧。

  模板

  div class= scaner ref= scaner

  !-提示框:用于在不兼容的浏览器中显示提示-

  div class= banner v-if= show banner

  I class= close _ icon @ click=()=show banner=false /I

  Class= text 如果当前浏览器无法扫描代码,请切换到另一个浏览器并尝试/p

  /div

  !-扫码框:显示扫码动画-

  div class=cover

  p class=line/p

  span class=方形左上/span

  span class=方形右上/span

  span class=右下方/span

  span class=左下方/span

  Class= tips 把二维码放在盒子里,就可以自动扫描了/p

  /div

  !-视频流显示-

  录像

  v-show=showPlay

  class=source

  ref=video

  :width=videoWH.width

  :height=videoWH.height

  控制

  /视频

  画布v-show=!showPlay ref=canvas /

  button-show= show play @ click= run 开始/button

  /div

  /模板

  方法:绘画

  画一条线。

  图片框(用于代码扫描成功后绘制矩形图形)。

  //画一条线

  绘制线(开始,结束){

  this . canvas . begin path();

  this.canvas.moveTo(begin.x,begin . y);

  this.canvas.lineTo(end.x,end . y);

  this . canvas . line width=this . line width;

  this . canvas . stroke style=this . line color;

  this . canvas . stroke();

  },

  //框架

  抽屉(位置){

  如果(this . drawn found){

  this . drawline(location . topleftcorner,location . toprightcorner);

  this . drawline(location . toprightcorner,location . bottom right corner);

  this . drawline(location . bottomrightcorner,location . bottomleftcorner);

  this . drawline(location . bottom left corner,location . topleftcorner);

  }

  },

  方法:初始化

  请检查它是否受支持。

  打开摄像机。

  已成功处理。

  //初始化

  setup () {

  //确定浏览器是否支持MediaDevices.getUserMedia()中的挂载方式

  if(navigator . media devices navigator . media devices . getuser media){

  this.previousCode=null

  this . parity=0;

  this.active=true

  this.canvas=this。$ refs . canvas . get context( 2d );

  //获取相机模式。默认设置是后置摄像头。

  const facing mode=this . useback camera?{ exact:环境 }:用户;

  //摄像机视频处理

  const handleSuccess=stream={

  如果(这个。$refs.video.srcObject!==未定义){

  这个。$ refs . video . src object=stream;

  } else if(窗口。视频El。mozsrcobject!==未定义){

  这个参考文献。视频。mozsrcobject=stream

  } else if(窗口URL.createObjectURL) {

  这个. refs.video.src=window .URL.createObjectURL(流);

  } else if (window.webkitURL) {

  这个参考文献。视频。src=窗口。webkiturl。createobjecturl(流);

  }否则{

  这个参考文献。视频。src=stream

  }

  //不希望用户来拖动进度条的话,可以直接使用playsinline属性,webkit-playsinline属性

  这个参考文献。视频。内嵌播放=true

  const playPromise=this .$参考文献。视频。play();

  玩诺言。catch(()=(这个。show play=true));

  //视频开始播放时进行周期性扫码识别

  玩诺言。然后(这个。跑);

  };

  //捕获视频流

  导航器。媒体设备。getuser media({ video:{ facing mode } })。然后(成功处理)。catch(()={

  导航器。媒体设备。getUserMedia({ video: true })。然后(成功处理)。接住(错误={

  这个$emit(错误捕获,错误);

  });

  });

  }

  },

  方法:周期性扫描

  run () {

  if (this.active) {

  //浏览器在下次重绘前循环调用扫码方法

  requestAnimationFrame(this。打勾);

  }

  },

  方法:成功回调

  //二维码识别成功事件处理

  找到(代码){

  if (this.previousCode!==代码){

  this.previousCode=代码

  } else if(这个。以前的代码===代码){

  这个。奇偶=1;

  }

  如果(this.parity 2) {

  this.active=this.stopOnScanned?假:真;

  这个。奇偶=0;

  这个$emit(代码扫描,代码);

  }

  },

  方法:停止

  //完全停止

  句号(){

  如果(这个.视频这个. refs $ video . src object){

  //停止视频流序列轨道

  这个参考文献。视频。src对象。获取曲目().forEach(t=t . stop());

  }

  }

  方法:扫描

  绘制视频帧。

  扫码识别。

  //周期性扫码识别

  tick () {

  //视频处于准备阶段,并且已经加载足够的数据

  如果(这个.视频这个. refs $ video . ready state===this .$refs.video.HAVE_ENOUGH_DATA) {

  //开始在画布上绘制视频

  这个参考文献。画布。身高=这个。视频wh。身高;

  这个参考文献。画布。宽度=这个。视频wh。宽度;

  this.canvas.drawImage(this .$refs.video,0,0,this .$refs.canvas.width,这个参考文献。画布。身高);

  //getImageData()复制画布上制定矩形的像素数据

  const imageData=this。画布。getimagedata(0,0,this .$refs.canvas.width,这个参考文献。画布。身高);

  设代码=假

  尝试{

  //识别二维码

  code=jsQR(imageData.data,imageData.width,imageData。身高);

  } catch (e) {

  控制台。错误(e)和:

  }

  //如果识别出二维码,绘制矩形框

  如果(代码){

  这个。绘制框(代码。位置);

  //识别成功事件处理

  这个。发现(代码。数据);

  }

  }

  这个。run();

  },

  父组件

  扫描仪的父组件主要加载页面,并展示扫描仪扫码结果的回调。

  页面结构

  模板

  div class=扫描

  !-页面导航栏-

  div class=" nav "

  一个class= close @ click=()=$路由器。go(-1)/a

  标题扫描四分之一码/p

  /div

  div class=滚动容器

  !-扫码子组件-

  扫描仪

  v-on:代码扫描=代码扫描

  v-on:错误捕获=错误捕获

  :扫描时停止=真

  :draw-on-found=true

  :responsive=false

  /

  /div

  /div

  /模板

  父组件方法

  从导入扫描仪./组件/扫描仪;

  导出默认值{

  名称:扫描,

  组件:{

  扫描仪

  },

  data () {

  返回{

  错误消息:"",

  已扫描:""

  }

  },

  方法:{

  代码扫描(代码){

  this.scanned=代码

  setTimeout(()={

  警报(` 1扫码解析成功:$[code]`);

  }, 200)

  },

  错误捕获(错误){

  开关(错误名称){

  案例" NotAllowedError ":

  this.errorMessage=相机权限被拒绝;

  打破;

  案例“未找到错误”:

  this.errorMessage=没有连接的摄像机。

  打破;

  案例“NotSupportedError”:

  this.errorMessage=

  似乎这个页面是在不安全的环境下提供的。

  打破;

  案例“NotReadableError”:

  this.errorMessage=

  无法访问您的相机。它已经被使用了吗?

  打破;

  case“over constrained error”:

  this.errorMessage=约束与任何已安装的摄像机都不匹配。

  打破;

  默认值:

  this.errorMessage=未知错误: error.message

  }

  console . error(this . error message);

  Alert(相机调用失败);

  }

  },

  已安装(){

  var str=navigator . user agent . tolowercase();

  var ver=str.match(/cpu iphone os(。*?)像MAC OS/);

  //经过测试,iOS 10.3.3以下系统无法成功调用摄像头。

  if (ver ver[1])。替换(/_/g,.) 10.3.3) {

  Alert(相机调用失败);

  }

  }

  完全码

  吉图布:https://github.com/dragonir/h5-scan-qrcode

  

总结

  

应用扩展

  我觉得通过浏览器调用摄像头,扫描识别,可以实现以下功能。你认为浏览器端扫码还能实现哪些令人惊艳的功能应用?

  链接跳转。

  价格查询。

  认证。

  下载文件。

  和睦相处

  即使使用了适配器,某些浏览器也不支持getUserMedia API。

  低版本浏览器(如iOS 10.3或以下)和Android小众浏览器(如IQOO自带浏览器)不兼容。

  QQ和微信内置浏览器无法调用。

  参考数据

  [1].使用WebRTC拍摄静态照片

  [2].使用mediaDevices API在JavaScript中选择摄像机

  [3].如何使用JavaScript访问设备的前置和后置摄像头

  作者:dragonir地址:https://www.cnblogs.com/dragonir/p/15405141.html

  关于vue的浏览器端扫码功能的这篇文章就到这里了。关于Vue浏览器代码扫描的更多信息,请搜索我们之前的文章或者继续浏览下面的相关文章。希望大家以后能多多支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: