使用原生JS实现拍照功能

 更新时间:2023年12月27日 10:20:13   作者:程序员大澈  
今天我们聊一聊,一个非常有趣且重要的问题,如何用原生js实现拍照功能?这时候,有的朋友会说,为什么要用原生js实现呀,这么麻烦还要自己动脑子,直接用第三方库多好呀,但是,你难道不好奇它的底层js实现吗?感兴趣的同学跟着小编一起来瞧瞧吧

1. 需求分析

今天我们聊一聊,一个非常有趣且重要的问题,如何用原生js实现拍照功能?

这时候,有的朋友会说,为什么要用原生js实现呀,这么麻烦还要自己动脑子,直接用第三方库多好呀。

说的没错,使用第三方库确实比较高效。所以,这里我们可以直接考虑使用第三方的js摄像库,如CameraJSWebcamJSgetUserMediaJS等,以便更高效地实现拍照功能。

但是,你难道不好奇它的底层js实现吗?也说不定未来某一刻会用到呢,毕竟其灵活性远超第三方库。

一起瞧瞧,原理其实很简单。

先明确一下,在项目中啥时候会用到拍照功能呢?

答:拍照功能在许多项目中都可以应用,以下是一些常见的需求场景

  • 社交媒体应用:社交媒体应用通常需要用户拍摄照片并上传到平台上,用于分享、发布动态或更改个人资料照片。
  • 电子商务应用:电子商务应用中,可以使用拍照功能让用户拍摄商品照片,以便上传至商品详情页或用于售后服务中。
  • 扫描和识别:拍照功能可以用于扫描和识别文档、二维码、条形码或身份证等信息。例如,应用可以使用拍照来扫描身份证,并自动提取身份信息。
  • 相机应用和照片编辑:相机应用需要拍照功能来捕捉照片,同时还可以提供各种照片编辑功能,如滤镜、裁剪、旋转等。
  • 实时图像处理:拍照功能结合图像处理技术,可以实现实时的图像滤镜、人脸识别、美颜等效果。
  • 身份验证和安全:某些应用需要拍照以进行身份验证或安全认证。例如,用户可以拍摄自己的面部照片,用于人脸识别进行登录或解锁。
  • 文档管理和归档:拍照功能可以用于文档管理和归档,用户可以通过拍照将纸质文档转换为电子格式,并进行保存和分类。

2. 功能实现

在明确了上述需求之后,我们正式开始拍照功能的原生js实现,分3步进行吧。我在后面还放了全部的代码,以及一些需要注意的事项。

2.1 获取媒体设备访问权限

先检验使用设备上是否有媒体设备,使用 navigator.mediaDevices.

enumerateDevices() 方法。

const navigator = window.navigator.mediaDevices;
const devices = await navigator.enumerateDevices();
if (devices) { ... }

再使用 navigator.mediaDevices.getUserMedia() 方法,请求用户的媒体设备权限,包括摄像头和麦克风。该方法会返回视频流数据。

const stream = await navigator.getUserMedia({
  audio: false, // 不需要音频
  video: {
    width: 300,
    height: 300,
    // facingMode: { exact: "environment" }, //强制后置摄像头
    facingMode: "user", //前置摄像头
  },
});

2.2 显示视频流

将获取到的视频流,绑定到HTML的 <video> 元素上,用于实时显示摄像头捕捉的画面。

if (!videoRef.value) return;
videoRef.value.srcObject = stream;
videoRef.value.play();

2.3 拍照截图

通过捕捉 <video> 元素的当前画面,可以实现拍照功能。你可以使用 <canvas> 元素的drawImage()方法来绘制视频画面,并将其转换为图像数据。

// 设置canvas画布  
const canvas = document.createElement("canvas");
canvas.width = videoRef.value.videoWidth;
canvas.height = videoRef.value.videoHeight;
// 获取canvas上下文对象
const ctx = canvas.getContext("2d");
// 截图操作
ctx?.drawImage(videoRef.value, 0, 0, canvas.width, canvas.height);

最后,你可以将获取到的图像数据,根据项目具体需求用于后续的操作,如显示、上传到服务器等。

2.4 全部代码

下面是拍照功能实现的全部代码,每行代码都已做好相应注释,复制粘贴即可直接使用:

<template>
  <div ref="wrapperRefRef">
    <video ref="videoRef" />
    <el-button type="primary" @click="handleShoot">拍摄</el-button>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";

const wrapperRef = ref();
const videoRef = ref();

// 检验设备
const checkCamera = async () => {
  // 先检验当前设备是否有摄像设备
  const navigator = window.navigator.mediaDevices;
  const devices = await navigator.enumerateDevices();

  // 如果有视频设备,则获取摄像头
  if (devices) {
    const stream = await navigator.getUserMedia({
      audio: false, // 不需要音频
      video: {
        width: 300,
        height: 300,
        // facingMode: { exact: "environment" }, //强制后置摄像头
        facingMode: "user", //前置摄像头
      },
    });

    console.log(stream);
    
    // 用video元素渲染流数据
    if (!videoRef.value) return;
    videoRef.value.srcObject = stream;
    videoRef.value.play();
  }
}

// 点击拍照
const handleShoot = () =>  {
  if (!videoRef.value || !wrapperRef.value) return;

  // 设置canvas画布  
  const canvas = document.createElement("canvas");
  canvas.width = videoRef.value.videoWidth;
  canvas.height = videoRef.value.videoHeight;
  // 获取canvas上下文对象
  const ctx = canvas.getContext("2d");
  // 截图操作
  ctx?.drawImage(videoRef.value, 0, 0, canvas.width, canvas.height);
  // 展示截图  
  wrapperRef.value.appendChild(canvas);
}

onMounted(() => {
  checkCamera();
});
</script>

2.5 一些注意事项

window.navigator.mediaDevices 中的 mediaDevices 属性,表示了浏览器是否支持使用媒体设备,如摄像头和麦克风。

在某些情况下,这个属性可能会在某些电脑上存在,而在其他电脑上不存在

其原因取决于多个因素,包括浏览器的支持程度用户权限设置网页的协议环境。如果你在某台电脑上发现该属性不存在,可能是因为其中一个或多个因素导致的。

我在做demo尝试时,进行了网页的分享,但不是通过 HTTPS 协议提供的,导致分享设备浏览器被限制了媒体访问,后面排查了好一段时间。

希望路过的朋友们不要再遇到,脑壳疼!

结语

以上就是使用原生JS实现拍照功能的详细内容,更多关于JS实现拍照功能的资料请关注脚本之家其它相关文章!

相关文章

  • javascript实现继承的简单实例

    javascript实现继承的简单实例

    这篇文章主要介绍了javascript实现继承的简单实例的相关资料,需要的朋友可以参考下
    2015-07-07
  • bootstrap时间控件daterangepicker使用方法及各种小bug修复

    bootstrap时间控件daterangepicker使用方法及各种小bug修复

    这篇文章主要介绍了bootstrap时间控件daterangepicker使用方法,及各种小bug修复,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 关于TypeScript中import JSON的正确姿势详解

    关于TypeScript中import JSON的正确姿势详解

    2012年10月首度对外公布typescript(当时已经是0.7?的版本)同时开源,ts的编译器是用js编写的(后来改成ts?),可以在线编写。下面这篇文章主要给大家介绍了关于TypeScript中import JSON的正确姿势,需要的朋友可以参考下。
    2017-07-07
  • JS是按值传递还是按引用传递

    JS是按值传递还是按引用传递

    在分析这个问题之前,我们需了解什么是按值传递(call by value),什么是按引用传递(call by reference)。在计算机科学里,这个部分叫求值策略(Evaluation Strategy)。它决定变量之间、函数调用时实参和形参之间值是如何传递的。
    2015-01-01
  • 原生js实现密码输入框值的显示隐藏

    原生js实现密码输入框值的显示隐藏

    这篇文章主要为大家详细介绍了原生js实现密码输入框值的显示隐藏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • 一文了解JavaScript中call/apply/bind的使用

    一文了解JavaScript中call/apply/bind的使用

    这篇文章主要介绍了一文了解JavaScript中call/apply/bind的使用,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下
    2022-07-07
  • bootstarp modal框居中显示的实现代码

    bootstarp modal框居中显示的实现代码

    这篇文章主要介绍了bootstarp modal框居中显示的实现代码,需要的朋友可以参考下
    2017-02-02
  • prettier自动格式化去换行的实现代码

    prettier自动格式化去换行的实现代码

    这篇文章主要介绍了prettier自动格式化去换行的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • location.search在客户端获取Url参数的方法

    location.search在客户端获取Url参数的方法

    最近一直在写html,刚接触到,感觉挺复杂的。。比如传参,在.net里可以直接用Request接受,而在html中还要经过处理,找了一些资料,写了个方法。
    2010-06-06
  • javascript搜索自动提示功能的实现

    javascript搜索自动提示功能的实现

    使用 jQuery(Ajax)/PHP/MySQL实现自动完成功我觉得我有必要写这个教程,因为曾经见到的大部分关于自动完成的应用程序都只是给你一个程序源码包,然后告诉你怎么使用,而不是告诉你它是如何工作的以及为什么这样做。
    2008-06-06

最新评论