浏览器切换摄像头实现拍照功能(复制可用)

253 阅读2分钟

对于之前功能的一个优化

在HTML中定义了一些元素和按钮,包括一个用于显示实时摄像头画面的<video>元素、用于预览拍摄照片的<canvas>元素以及拍照、切换摄像头、重拍和上传照片等操作的按钮。

  • startCamera函数用于开启摄像头,通过getUserMedia方法获取用户的摄像头权限,并将摄像头画面显示在<video>元素中。
  • switchCamera函数用于切换摄像头,通过选择摄像头列表中的某个摄像头,调用startCamera函数重新开启摄像头。
  • getVideoList函数用于获取摄像头设备列表,通过enumerateDevices方法获取所有设备列表,并筛选出视频设备。
  • takePicture函数用于拍照,使用drawImage方法将摄像头画面绘制在<canvas>元素中,同时在<canvas-preview>元素中显示预览图片。
  • reset函数用于重拍,将预览画面和绘制在<canvas>上的照片清空,同时显示拍照按钮。
  • uploadPhoto函数用于上传照片,将拍摄的照片转换成DataURL格式,调用window.opener中的某个函数,并传递照片数据URL作为参数,最后关闭当前窗口。
  • 最后,在页面加载完成后,调用getVideoList函数获取摄像头列表,将列表中的摄像头选项添加到<select>元素中供用户选择使用。

这段代码可以作为一个拍照功能的演示示例,并可以根据需要进行修改和扩展。

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>拍照</title>
  <style type="text/css">
    #canvas-preview {
      position: absolute;
      left: 0;
      right: 0;
      top: 10px;
      margin: auto;
      background: white;
      display: none;
    }
  </style>
</head>
<body style="text-align: center; margin: 0;">
<canvas id="canvas" style="position: absolute; top: -5000px;" width="1280" height="960"></canvas>
<video id="video" style="margin: 10px;"></video>
<canvas id="canvas-preview"></canvas>
<button id="takeIt" class="btn" onclick="takePicture()">拍照</button>
<select id="selectCamera" onchange="switchCamera()">
  <option value="">请选择摄像头</option>
</select>
<button id="reClear" class="btn" onclick="reset()" style="display: none;">重拍</button>
<button id="upload" class="btn" onclick="uploadPhoto()" style="display: none;">上传</button>
</body>
<script type="text/javascript">
  var preview = document.getElementById('canvas-preview')
  var canvas = document.getElementById('canvas')

  var takeIt = document.getElementById('takeIt')
  var reClear = document.getElementById('reClear')
  var upload = document.getElementById('upload')
  var selectCamera = document.getElementById('selectCamera')
  var videoList = []
  getVideoList()
  // 开启摄像头
  function startCamera(cameraIndex) {
    var video = document.getElementById('video')
    var constraints = {
      audio: false,
      video: {
        width: { ideal: 1280 },
        height: { ideal: 960 },
        deviceId: { exact: videoList[cameraIndex].deviceId }
      }
    }
    navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
      video.srcObject = stream
      video.play()
      // selectCamera.style.display = 'none'
      takeIt.style.display = 'unset'
      reClear.style.display = 'none'
      upload.style.display = 'none'
    }, function() {
      alert('获取摄像头权限失败')
    })
  }

  // 切换摄像头
  function switchCamera() {
    var selectedCamera = selectCamera.value
    if (selectedCamera == "") {
      return;
    }
    startCamera(parseInt(selectedCamera))
  }

  // 获取摄像头设备列表
  function getVideoList() {
    return new Promise((resolve, reject) => {
      navigator.mediaDevices.enumerateDevices().then((devices) => {
        const videoList = devices.filter(device => device.kind === 'videoinput')
        resolve(videoList)
      }).catch((err) => {
        reject(err)
      })
    })
  }

  // 拍照、canvas绘制
  function takePicture() {
    var w = window.innerWidth - 50, h = window.innerHeight - 50
    var video = document.getElementById('video')
    var previewCnt = preview.getContext('2d')
    var context = canvas.getContext('2d')

    preview.style.display = 'block'
    takeIt.style.display = 'none'
    reClear.style.display = 'unset'
    upload.style.display = 'unset'
    previewCnt.drawImage(video, 0, 0, w, h)
    context.drawImage(video, 0, 0, 1280, 960)
  }

  // 重拍
  function reset() {
    var w = window.innerWidth - 50, h = window.innerHeight - 50
    var previewCnt = preview.getContext('2d')
    var context = canvas.getContext('2d')

    previewCnt.clearRect(0, 0, w, h)
    context.clearRect(0, 0, 1280, 960)
    preview.style.display = 'none'
    takeIt.style.display = 'unset'
    reClear.style.display = 'none'
    upload.style.display = 'none'
  }

  // 上传图片
  function uploadPhoto() {
    var photo = window.location.href.split('?')[1]
    var dataURL = canvas.toDataURL('image/jpeg')
    eval(' window.opener.' + photo + '(dataURL)')
    window.close()
  }

  // 获取摄像头列表
  getVideoList().then((devices) => {
    videoList = devices
    if (videoList.length === 0) {
      alert('没有检测到摄像头设备!')
      return
    }
    selectCamera.style.display = 'unset'
    for (var i = 0; i < videoList.length; i++) {
      var option = document.createElement('option')
      option.setAttribute('value', i)
      option.innerText = videoList[i].label
      selectCamera.appendChild(option)
    }
  }).catch((err) => {
    alert('获取摄像头列表失败:' + err)
  })
</script>
</html>