[04天]Web端打打开用户摄像头拍照mediaDevices

在Web端打打开用户摄像头拍照,是通过navigator对象的新API mediaDevices对象实现。

先来一个完整例子:

打开用户摄像头播放录制内容,实时拍照下载

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>mediaDevices Demo</title>
</head>
<body>
  <p>
    <button id="open">打开</button>
    <button id="close">关闭</button></button>
    <button id="picture">拍照</button></button>
  </p>
  <video></video>
<script>
class MediaDevices{
  constructor(videoDom) {
    if (!this.test()) {
      console.log('浏览器不支持')
      return
    }
    this.video = videoDom
    this.stream = null
  }

  // 测试浏览器是否已经支持该API
  test() {
    return !!navigator?.mediaDevices?.getUserMedia
  }
  // 打开并获取摄像头数据
  getUserMedia() {
    const constraints = window.constraints = {
      audio: true, // 获取音频
      video: true, // 获取视频
    }
    navigator.mediaDevices.getUserMedia(constraints)
    .then(stream => {
      stream.onended = function() {
        console.log('数据流结束')
      }
      this.stream = stream
      this.video.srcObject = stream
      this.video.play()
    })
    .catch(error => {
      console.log(error)
    })
  }
  // 拍照并下载
  takePicture() {
    const canvas = document.createElement('canvas')
    canvas.width = this.video.videoWidth
    canvas.height = this.video.videoHeight
    const ctx = canvas.getContext('2d')
    ctx.drawImage(this.video, 0, 0, canvas.width, canvas.height)
    const a = document.createElement('a')
    a.href = canvas.toDataURL()
    a.download = new Date().getTime() + '.jpg'
    a.dispatchEvent(new MouseEvent('click'))
  }
  // 停止
  stop() {
    this.video.pause()
    this.stream.getTracks().forEach(track => track.stop())
  }
}

const md = new MediaDevices(document.querySelector('video'))
document.querySelector('#open').addEventListener('click', () => {
  md.getUserMedia()
})
document.querySelector('#close').addEventListener('click', () => {
  md.stop()
})
document.querySelector('#picture').addEventListener('click', () => {
  md.takePicture()
})
</script>
</body>
</html>


分解

class MediaDevices{
  constructor(videoDom) {
    if (!this.test()) {
      console.log('浏览器不支持')
      return
    }
    this.video = videoDom
    this.stream = null
  }

  // 测试浏览器是否已经支持该API
  test() {
    return !!navigator?.mediaDevices?.getUserMedia
  }
  // ...
}

先创建一个类, 接收显示视频用的video标签,并写一个测试浏览器是否支持 mediaDevices API 的方法


class MediaDevices{
  // ...
  // 打开并获取摄像头数据
  getUserMedia() {
    const constraints = window.constraints = {
      audio: true, // 获取音频
      video: true, // 获取视频
    }
    navigator.mediaDevices.getUserMedia(constraints)
    .then(stream => {
      stream.onended = function() {
        console.log('数据流结束')
      }
      this.stream = stream
      this.video.srcObject = stream
      this.video.play()
    })
    .catch(error => {
      console.log(error)
    })
  }
  // ...
}

添加核心方法

使用 mediaDevices.getUserMedia 方法打开摄像头,并将获取到的流做为srcObject 加载到video标签。然后播放video。


class MediaDevices{
  // ...
  // 拍照并下载
  takePicture() {
    const canvas = document.createElement('canvas')
    canvas.width = this.video.videoWidth
    canvas.height = this.video.videoHeight
    const ctx = canvas.getContext('2d')
    ctx.drawImage(this.video, 0, 0, canvas.width, canvas.height)
    const a = document.createElement('a')
    a.href = canvas.toDataURL('image/jpeg', 1.0)
    a.download = new Date().getTime() + '.jpg'
    a.dispatchEvent(new MouseEvent('click'))
  }
  // ...
}

再添加一个拍照的方法

创建一个离屏画布,然后抓取视频帧画到画布上。

创建一个a标签,使用toDataURL API将画布中的图像转为DataURL做为a标签的href属性

对a标签触发一个点击事件,触发浏览器执行下载

至此打开摄像头拍照的目的达成


class MediaDevices{
  // ...
  // 停止
  stop() {
    this.video.pause()
    this.stream.getTracks().forEach(track => track.stop())
  }
}

最后再添加一个停止视频播放,关闭摄像头方法。


扩展

mediaDevices.getDisplayMedia() 获取用户屏幕

提示用户选择显示器或显示器的一部分(例如窗口)以捕获为MediaStream 以便共享或记录。返回解析为MediaStream的Promise

提示:可将上例中的 getUserMedia 方法 替换为 getDisplayMedia 方法进行体验


扩展资料查阅: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices

2022-05-20 20:00:11 522 0

参与讨论

选择你的头像