在React项目中实现调用摄像头拍照的功能

7 篇文章 0 订阅
5 篇文章 0 订阅


前言

在日常开发中可能会遇到需要调用摄像头拍照的功能,下面为大家讲解一下在react项目当中如何实现拍照的功能。


一、如何调用摄像头

调用摄像头只需要用到JS原生的api就可以了navigator.mediaDevices.getUserMedia,关于这个api,mdn有详细的介绍MediaDevices.getUserMedia()

二、操作步骤

1.准备dom元素

video 用于展示获取到的视频资源
canvas 用于生成图片

代码如下(示例):

import React, { useRef } from 'react';
const CameraComponent = () => {

 const cameraVideoRef = useRef(null);
 const cameraCanvasRef = useRef(null);

return(
 <div>
   <video
     id="cameraVideo"
     ref={cameraVideoRef}
     style={{
       position: 'absolute', top: '30px', height: '500px', width: '900px'
     }}
    />
    <canvas
      id="cameraCanvas"
      ref={cameraCanvasRef}
      width={pictureSize.width}
      height={pictureSize.height}
      style={{
        width: '900px', height: '500px'
      }}
    />
 </div>
)
}

2.添加打开和关闭摄像头的事件

代码如下(示例):


import React, { useRef } from 'react';
const CameraComponent = () => {

 const cameraVideoRef = useRef(null);
 const cameraCanvasRef = useRef(null);

  function successFunc(mediaStream) {
    const video = cameraVideoRef.current;
    // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
    // 旧的浏览器可能没有srcObject
    if ('srcObject' in video) {
      video.srcObject = mediaStream;
    }
    video.onloadedmetadata = () => {
      video.play();
    };
  }

  function errorFunc(err) {
    console.log(`${err.name}: ${err.message}`);
    // always check for errors at the end.
  }
    // 启动摄像头
  const openMedia = () => { // 打开摄像头
    const opt = {
      audio: false,
      video: {
        width: 1280,
        height: 720
      }
    };
    navigator.mediaDevices.getUserMedia(opt).then(successFunc).catch(errorFunc);
  };
  // 关闭摄像头
  const closeMedia = () => {
    // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
    const video = cameraVideoRef.current;
    const stream = video.srcObject;
    if ('getTracks' in stream) {
      const tracks = stream.getTracks();
      tracks.forEach(track => {
        track.stop();
      });
    }
  };

return(
 <div>
   <video
     id="cameraVideo"
     ref={cameraVideoRef}
     style={{
       width: '1280px', height: '720px'
     }}
    />
    <canvas
      id="cameraCanvas"
      ref={cameraCanvasRef}
      width={1280}
      height={720}
      style={{
        width: '1280px', height: '720px'
      }}
    />
    <button onClick={openMedia} >打开摄像头</button>
    <button onClick={} >保存</button>
    <button onClick={closeMedia} >关闭摄像头</button>
 </div>
)
}

3.获取图片 base64格式

  const getImg = () => {
    // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
    // const canvas = document.getElementById('cameraCanvas') as HTMLCanvasElement;
    const video = cameraVideoRef.current;
    const canvas = cameraCanvasRef.current;
    if (canvas == null) {
      return;
    }
    const ctx = canvas.getContext('2d');
    ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); // 把视频中的一帧在canvas画布里面绘制出来
    const imgStr = canvas.toDataURL(); // 将图片资源转成字符串
    const base64Img = imgStr.split(';base64,').pop(); // 将图片资源转成base64格式
    const imgData = {
      base64Img
    };
    closeMedia(); // 获取到图片之后可以自动关闭摄像头
    return imgData;
  };


获取到图片资源以后我们可以把base64字符串发给后端,也可以直接放在img元素中显示拍摄的照片。

const saveImg = () => { // electron项目保存到本地
  const data = getImg();
  document.getElementById('imgTag').src = data.base64Img
};

如果是electron的项目还可以通过fs的方法将图片直接保存到本地。

const path = require('path')
const os = require('os')
const saveImg = () => { // electron项目保存到本地
  const imgFilePath = path.join(os.homedir(), 'Desktop', 'img.png')//文件存储的路径
  const data = getImg();
   // 使用同步的文件写入方法 保证有返回值的时候文件已经存储完毕
  fs.writeFileSync(imgFilePath, data.base64Img, { encoding: 'base64' }, error => {
    if (error) {
      console.log(error);
      return false;
    }
    console.log('write success');
  });
};

也可以在网页中直接保存图片

const saveImg = () => { // electron项目保存到本地
  const data = getImg();
  // 网页保存图片的方法
  const saveLink = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
  saveLink.href = data.base64Img;
  saveLink.download = './i.png';
  const event = document.createEvent('MouseEvents');
  event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  saveLink.dispatchEvent(event);
};

三、demo

代码如下(示例):


import React, { useRef } from 'react';
const CameraComponent = () => {

 const cameraVideoRef = useRef(null);
 const cameraCanvasRef = useRef(null);

  function successFunc(mediaStream) {
    const video = cameraVideoRef.current;
    // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
    // 旧的浏览器可能没有srcObject
    if ('srcObject' in video) {
      video.srcObject = mediaStream;
    }
    video.onloadedmetadata = () => {
      video.play();
    };
  }

  function errorFunc(err) {
    console.log(`${err.name}: ${err.message}`);
    // always check for errors at the end.
  }
    // 启动摄像头
  const openMedia = () => { // 打开摄像头
    const opt = {
      audio: false,
      video: {
        width: 1280,
        height: 720
      }
    };
    navigator.mediaDevices.getUserMedia(opt).then(successFunc).catch(errorFunc);
  };
  // 关闭摄像头
  const closeMedia = () => {
    // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
    const video = cameraVideoRef.current;
    const stream = video.srcObject;
    if ('getTracks' in stream) {
      const tracks = stream.getTracks();
      tracks.forEach(track => {
        track.stop();
      });
    }
  };

  const getImg = () => { // 获取图片资源
    // const video = document.getElementById('cameraVideo') as HTMLVideoElement;
    // const canvas = document.getElementById('cameraCanvas') as HTMLCanvasElement;
    const video = cameraVideoRef.current;
    const canvas = cameraCanvasRef.current;
    if (canvas == null) {
      return;
    }
    const ctx = canvas.getContext('2d');
    ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight); // 把视频中的一帧在canvas画布里面绘制出来
    const imgStr = canvas.toDataURL(); // 将图片资源转成字符串
    const base64Img = imgStr.split(';base64,').pop(); // 将图片资源转成base64格式
    const imgData = {
      base64Img
    };
    closeMedia(); // 获取到图片之后可以自动关闭摄像头
    return imgData;
  };


const saveImg = () => { // electron项目保存到本地
  const data = getImg();
  document.getElementById('imgTag').src = data.base64Img
  // 网页保存图片的方法
  const saveLink = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
  saveLink.href = data.base64Img;
  saveLink.download = './i.png';
  const event = document.createEvent('MouseEvents');
  event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
  saveLink.dispatchEvent(event);
};

return(
 <div>
   <video
     id="cameraVideo"
     ref={cameraVideoRef}
     style={{
       width: '1280px', height: '720px'
     }}
    />
    <canvas
      id="cameraCanvas"
      ref={cameraCanvasRef}
      width={1280}
      height={720}
      style={{
        width: '1280px', height: '720px'
      }}
    />
    <img id="imgTag" src="" alt="imgTag"/>
    <button onClick={openMedia} >打开摄像头</button>
    <button onClick={saveImg} >保存</button>
    <button onClick={closeMedia} >关闭摄像头</button>
 </div>
)
}


总结

以上就是今天要讲的内容,本文仅仅简单介绍了js调用摄像头拍照的案例,如果大家在使用过程中遇到了问题可以在评论区留言哦。

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值