如何在 PWA 中访问相机

已发表: 2020-08-19

目录

以前在我们详细介绍 PWA 的硬件功能的文章中介绍过,摄像头访问是我们越来越多地看到的更突出的功能之一。 但是要将这种能力正确地集成到你的 PWA 中也不是一件容易的事,这就是为什么在我们今天的文章中,我们将尝试引导你完成整个过程:

先决条件

  • 可以使用 ReactJS 和我们的书面指南轻松创建的基本 PWA
  • 对 HTML 和 JavaScript 有扎实的理解

如何在 PWA 中访问相机

基础知识

介绍getUserMedia() — webRTC 的 API

为了直接访问摄像头和/或麦克风,Web 使用了一个名为getUserMedia()的 API,几乎所有现代浏览器都广泛支持该 API。 此 API 以及RTCPeerConnectionRTCDataChannel是 WebRTC 的一部分——WebRTC 是一个内置于浏览器中的框架,可以实现实时通信。

基本上,API ( navigator.mediaDevices.getUserMedia(constraints) ) 的作用是提示用户允许访问电话的音频和视频输入(例如,麦克风、网络摄像头、摄像头等)。 使用该权限,API 会生成一个名为localMediaStream JavaScript 对象,该对象可以进一步操作。

例子

比如说,我们有一个按钮:

 <button>露出我的脸</button>

并单击哪个按钮调用navigator.mediaDevices.getUserMedia()方法(无音频输入):

 navigator.mediaDevices.getUserMedia({
 视频:真实
})

哎呀,我们也可以疯狂地使用约束:

 navigator.mediaDevices.getUserMedia({
  视频: {
    最小纵横比:1.333,
    最小帧率:30,
    宽度:1280,
    身高:720
  }
})

此外,我们可以在 video 对象中指定facingMode属性,它告诉浏览器使用设备的哪个摄像头:

 {
  视频: {
    ...
    面对模式:{
//使用后置摄像头
      确切的:'环境'
    }
  }
}

或者

 {
 视频 : {
  …
//使用前置摄像头
  面对模式:'用户'
 }
}

备注

  • API 仅在安全来源 (HTTPS) 上可用
  • 要获取当前设备上支持的约束列表,请运行:
 navigator.mediaDevices.getSupportedConstraints()

复杂的部分

现在我们已经对基础有了扎实的了解,让我们继续进行高级部分。 在这一部分中,我们将尝试在 PWA 中创建一个按钮,单击该按钮后,它会打开我们的相机并让我们做进一步的工作。

创建[Get access to camera]按钮

首先,让我们从 index.html 中的<button>开始:

 <button>访问相机</button>
<视频自动播放></video>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

  • 自动播放用于告诉媒体流自动播放而不是在第一帧冻结。
  • adapter-latest.js 是一个垫片,用于将应用程序与规范更改和前缀差异隔离开来。

通过单击按钮实时流式传输视频

要在单击按钮时实时流式传输视频,我们需要添加一个EventListener ,它会在发出click事件时调用:

 document.querySelector('#get-access').addEventListener('click', async function init(e) {
  尝试 {
 }
捕捉(错误){
 }
})

之后,它调用navigator.mediaDevices.getUserMedia()并使用设备的网络摄像头请求视频流:

 document.querySelector('#get-access').addEventListener('click', async function init(e) {
  尝试 {
    常量流 = 等待 navigator.mediaDevices.getUserMedia({
      音频:假,
      视频:真实
    })
    常量 videoTracks = stream.getVideoTracks()
    常量轨道 = videoTracks[0]
    alert(`从 ${track.label} 获取视频`)
    document.querySelector('video').srcObject = 流
    document.querySelector('#get-access').setAttribute('hidden', true)
//视频流在播放3秒后被track.stop()停止。
    setTimeout(() =&gt; { track.stop() }, 3 * 1000)
  } 捕捉(错误){
    警报(`${error.name}`)
    控制台.错误(错误)
  }
})

此外,如上文“基本”部分所述,您还可以为视频流指定更多要求:

 navigator.mediaDevices.getUserMedia({
  视频: {
    强制:{ minAspectRatio: 1.333, maxAspectRatio: 1.334, facesMode: 'user'},
    可选的: [
      { minFrameRate: 60 },
      { 最大宽度:640 },
      { 最大高度:480 }
    ]
  }
},成功回调,错误回调);

创建画布

<video>元素与<canvas>结合使用,您可以进一步处理我们的实时视频流。 这包括执行各种效果的能力,例如应用自定义滤镜、色度键控(又名“绿屏效果”)——所有这些都使用 JavaScript 代码。

如果您想了解更多有关此内容的信息,Mozilla 编写了有关使用画布操作视频的详细指南,因此请不要忘记查看!

使用takePhoto()grabFrame()捕捉画布的快照

getUserMedia API 的新takePhotograbFrame方法可用于捕获当前流视频的快照。 两种方法之间仍然存在显着差异:

基本上, grabFrame所做的只是抓取下一个视频帧——这是一种简单且不那么有效的拍照方法。 另一方面, takePhoto方法使用一种更好的捕获帧的方法,即通过中断当前视频流来使用相机的“最高可用摄影相机分辨率”来捕获 Blob 图像。

在下面的示例中,我们将使用grabFrame方法将捕获的帧绘制到canvas元素中:

 var grabFrameButton = document.querySelector('button#grabFrame');
var canvas = document.querySelector('canvas');

grabFrameButton.onclick = grabFrame;

函数抓取帧(){
  imageCapture.grabFrame()
  .then(函数(imageBitmap){
    console.log('抓取的帧:', imageBitmap);
    canvas.width = imageBitmap.width;
    canvas.height = imageBitmap.height;
    canvas.getContext('2d').drawImage(imageBitmap, 0, 0);
    canvas.classList.remove('隐藏');
  })
  .catch(函数(错误){
    console.log('grabFrame() 错误:',错误);
  });
}

在这个例子中,我们使用了takePhoto()方法:

 var takePhotoButton = document.querySelector('button#takePhoto');
var canvas = document.querySelector('canvas');

takePhotoButton.onclick = 拍照;

// 从当前选择的相机源中获取一个 Blob 和
// 用 img 元素显示它。
功能拍照(){
  imageCapture.takePhoto().then(function(blob) {
    console.log('拍照:', blob);
    img.classList.remove('隐藏');
    img.src = URL.createObjectURL(blob);
  }).catch(函数(错误){
    console.log('takePhoto() 错误:',错误);
  });
}

要了解上述方法的实际效果,我们建议使用 Simple Image Capture; 或者,PWA 媒体捕获也是 PWA 中基本媒体捕获功能的一个很好的例子。

结论

在本教程中,我们向您介绍了在 PWA 中实现相机功能的基础知识和一些高级技巧。 其余的只是您的想象力,以充分利用此功能。

对于希望开发下一代 PWA 支持的商店的 Magento 商家,在 SimiCart 中,我们根据您的需求提供完整的 PWA 解决方案。

探索 simicart PWA