原生js能否调用摄像头?

Daotin 于 2024-09-04 发布 编辑

这其实需要分 2 种,一种分调用手机的摄像头,一种是调用桌面端的摄像头。

调用手机摄像头

调用手机的摄像头比较简单,使用 input 的 capture 属性即可。

示例代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Camera Capture with Input Element</title>
  </head>
  <body>
    <input type="file" accept="image/*" capture="environment" id="cameraInput" />
    <img id="preview" style="max-width: 100%; display: none" alt="Preview of captured image" />

    <script>
      const cameraInput = document.getElementById('cameraInput');
      const preview = document.getElementById('preview');
      const uploadButton = document.getElementById('upload');
      const status = document.getElementById('status');
      let imageFile;

      cameraInput.addEventListener('change', (event) => {
        imageFile = event.target.files[0];
        if (imageFile) {
          const reader = new FileReader();
          reader.onload = (e) => {
            preview.src = e.target.result;
            preview.style.display = 'block';
            uploadButton.style.display = 'block';
          };
          reader.readAsDataURL(imageFile);
        }
      });
    </script>
  </body>
</html>

其中,

对于capture="user",在 IOS 系统是可以打开前置的,安卓的大部分机型都忽略了这个属性。打开的依然是后置摄像头。 有的浏览器甚至对capture="environment"都无效,直接打开了相册。。。

调用桌面摄像头

桌面浏览器一般不支持通过 <input> 标签的 capture 属性直接调用摄像头。因此,在桌面浏览器上,如果你想实现摄像头的访问功能,通常需要使用 getUserMedia API 来获取摄像头的视频流。

getUserMedia 是目前在桌面浏览器中唯一可以访问摄像头、麦克风等媒体设备的标准方式,它可以让你实时访问和操作视频、音频流。相比于移动设备上使用 capture 属性的简单操作,getUserMedia 提供了更多的控制和灵活性。

使用 getUserMedia 拍照的步骤:

  1. 使用 navigator.mediaDevices.getUserMedia({ video: true }) 请求访问摄像头。
  2. 将摄像头的实时视频流展示在 <video> 元素中,可以实时预览
  3. 当用户点击“拍照”按钮时,将视频帧绘制到 <canvas> 上,模拟拍照。
  4. 将 canvas 上的图像数据转换为所需的格式,通常是使用toDataURL()方法转为 base64 编码的字符串或使用toBlob()方法转为 Blob 对象
  5. 显示图片,可以将获取的图像数据显示在<img>元素中,或者准备用于上传。

具体代码:

<!DOCTYPE html>
<html>
  <body>
    das
    <video id="video" width="640" height="480" autoplay></video>
    <button id="capture">Take Photo</button>
    <canvas id="canvas" width="640" height="480" style="display: none"></canvas>
    <img id="photo" alt="Your captured image will appear here." />

    <script>
      const video = document.getElementById('video');
      const canvas = document.getElementById('canvas');
      const photo = document.getElementById('photo');
      const captureButton = document.getElementById('capture');

      // Step 1: Get camera access
      navigator.mediaDevices
        .getUserMedia({ video: true })
        .then((stream) => {
          // Step 2: Display video stream
          video.srcObject = stream;
        })
        .catch((error) => console.error('Error accessing the camera:', error));

      captureButton.addEventListener('click', () => {
        // Step 3: Capture image
        canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);

        // Step 4: Convert image
        const imageDataUrl = canvas.toDataURL('image/jpeg');

        // Step 5: Display image
        photo.src = imageDataUrl;
        photo.style.display = 'block';
      });
    </script>
  </body>
</html>

注意:出于安全考虑,getUserMedia()通常只在安全上下文(如 HTTPS)中可用。

推荐参考文章:https://github.com/iotale/garden/issues/26