js获取摄像头权限实现拍照功能

657 阅读2分钟

首先说一下js打开摄像头的流程:

  1. 使用getUserMedia打开摄像头然后将获取到的流媒体转成url放在video标签中的src中;
  2. 使用canvas的drawImage方法将video的内容绘至canvas中,这样就形成了截图的效果;
  3. 使用stream.getTracks()[0].stop()关闭摄像头。

1.开启摄像头

开启摄像头主要有两种方法,一个是旧方法window.navigator.getUserMedia()方法,还有一个就是新方法navigator.mediaDevices.getUserMedia()。旧方法的使用如下:

 btn1.addEventListener("click", function (event) {
            if ("getUserMedia" in window.navigator) {
                window.navigator.getUserMedia({
                    video: true,
                    audio: false
                }, function (stream) {
                    v1.srcObject = stream;
                    v1.play();
                }, function (err) {
                    console.error("获取摄像头视频错误");
                })
            }
        });

其中window.navigator.getUserMedia()方法的参数有三个。

  1. 第一个参数是一个对象,用于选择是否使用视频(video)和audio(audio)。
  2. 第二个参数是成功的回调,其中带一个参数(stream),在旧版本中可以直接通过调用MediaStream.stop() 来关闭摄像头,不过在新版之中已废弃。需要使用MediaStream.getTracks()[index].stop() 来关闭相应的Track 。
  3. 第三个参数是失败的回调,他有一个参数err用于接收错误,可以在控制台打印出来。

新方法的getUserMedia 位于navigator.mediaDevices对象下面,使用方法如下:

      btn1.addEventListener("click", function () {
        if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
          navigator.mediaDevices.getUserMedia({
            video: true,
            Audio: true
          }).then(function (stream) {
           mediaStreamTrack =  stream.getTracks()[0];
            btn2.addEventListener("click", function () {
              mediaStreamTrack.stop();
            }, false);
            video.srcObject = stream;
            video.play();
          }).catch(function (err) {
            console.log(err);
          })
        }
      });

这个新方法返回的是一个Promise对象,可以使用then和catch表示成功与失败的回调。其中的btn2的监听事件是关闭摄像头的,在下文会说明。 这里我想说的是第一次用这个新方法的时候有点问题,我准备用URL.createObjectURL()这个方法将流媒体转成一个地址然后放在video标签的src中,但是浏览器给我来了这么一下:

image.png

我就查了一下MDN发现他给出了下面的解释:

image.png

感兴趣的可以去这里看看URL.createObjectURL() 解决的方法如下: 原先的代码:

     video.src = URL.createObjectURL(stream);

更改成下面的代码:

    video.srcObject = stream;

兼容版本如下:

    try {
      this.srcObject = stream;
    } catch (error) {
      this.src = window.URL.createObjectURL(stream);
    }

2.使用canvas截图

代码如下:

    var photo = document.querySelector("#photo");
    var ctx = photo.getContext("2d");
    btn3.addEventListener("click", function () {
        ctx.drawImage(video, 0, 0, 300, 300);
    }, false)

3.关闭摄像头

在旧版本中可以直接使用stream.stop()来关闭摄像头,不过现在好像已经不行了所以我直接跳过使用新方法stream.getTracks()来关闭摄像头。

     var mediaStreamTrack =  stream.getTracks()[0];
     btn2.addEventListener("click", function () {
         mediaStreamTrack.stop();
     }, false);

这里需要注意的是返回的stream.getTracks()返回的Tracks数组是倒序排列的,例如video在第一个audio在第二个,那么stream.getTracks()[1]就是video。不过我在本例中只获取到了video,我也不知道为啥....所以只能用下标0。