功能问题:如何在H5中实现拍照功能?3步搞定!

大家好,我是大澈!

本文约2100+字,整篇阅读大约需要4分钟。

感谢关注微信公众号:“程序员大澈”,免费领取"面试礼包"一份,然后免费加入问答群,从此让解决问题的你不再孤单!

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 协议提供的,导致分享设备浏览器被限制了媒体访问,后面排查了好一段时间。

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

结语

建立这个平台的初衷:

  • 打造一个专注于前端功能问题的问答平台,让大家高效搜索处理同样问题。

  • 通过不断积累问题,一起练习逻辑思维,并顺便学习相关知识点。

  • 遇到有共鸣的问题,与众多同行朋友们一起讨论,一起沉淀成长。

  • 为了给功能问题专栏添加乐趣,增设技术资讯、实用干货两个新专栏。

感谢关注微信公众号:“程序员大澈”,免费领取"面试礼包"一份,然后免费加入问答群,从此让解决问题的你不再孤单!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/272404.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python 面试题第一弹

1. 如何理解Python中的深浅拷贝 浅拷贝&#xff08;Shallow Copy&#xff09;创建一个新的对象&#xff0c;该对象的内容是原始对象的引用。这意味着新对象与原始对象共享相同的内存地址&#xff0c;因此对于可变对象来说&#xff0c;如果修改了其中一个对象&#xff0c;另一个…

odoo17核心概念view7——listview总体框架分析

这是view系列的第七篇文章&#xff0c;今天主要介绍我们最常用的list视图。 1、先看list_view,这是主文件 /** odoo-module */import { registry } from "web/core/registry"; import { RelationalModel } from "web/model/relational_model/relational_mode…

Spring中常见的Bean后处理器

Bean后处理器的作用&#xff1a;为Bean生命周期各个阶段提供扩展。接下来我们查看一个案例 public class TestBeanPostProcessor {public static void main(String[] args) {//该容器不存在任何Spring中的bean对象&#xff0c;是一个干净的容器&#xff0c;且提供了正常容器中…

运动轨迹仿真

重型运载火箭轨迹/总体参数一体化优化方法 硬核推导火箭运动方程&#xff0c;并用python仿真实现 rocket-simulation:MATLAB-火箭仿真软件 MatRockSim:Matlab 火箭飞行模拟器 【开源】飞鹰一号探空火箭——箭体设计、制造回顾与仿真对比 偏航角&#xff0c;滚动角&#xf…

基于双闭环PI的SMO无速度控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于双闭环PI的SMO无速度控制系统simulink建模与仿真&#xff0c;基于双闭环PI的SMO无速度控制系统主要由两个闭环组成&#xff1a;一个是电流环&#xff0c;另一个是速度环。…

2024深入评测CleanMyMac X4.14.6破解版新的功能

随着时间的推移&#xff0c;我们的Mac电脑往往会变得越来越慢&#xff0c;存储空间变得越来越紧张&#xff0c;这时候一个优秀的清理工具就显得尤为重要。作为一款备受好评的Mac清理工具&#xff0c;它能够为你的Mac带来全方位的清理和优化。在本文中&#xff0c;我们将深入评测…

中科驭数与宽睿科技达成战略合作,共筑超低时延软硬一体技术底座

近日&#xff0c;中科驭数&#xff08;北京&#xff09;科技有限公司&#xff08;简称“中科驭数”&#xff09;和上海宽睿信息科技有限责任公司&#xff08;简称“宽睿科技”&#xff09;完成战略合作协议签署。双方将结合各自在超低时延软硬件领域的深厚业务积累和技术产品优…

晶振的起振温度对电子设备的影响

晶振&#xff0c;作为电子设备中的关键元件&#xff0c;其性能参数对设备的稳定性和可靠性具有重要影响。其中&#xff0c;晶振的起振温度是决定其工作性能的重要因素之一。晶发电子将探讨晶振起振温度对电子设备的影响以及如何应对这些影响。 首先&#xff0c;我们要了解什么…

2023/12/26中断作业

成果图&#xff1a; 代码&#xff1a; 函数层 key_it.c #include "key_init.h" void key1_it_config() { //RCC时钟RCC->MP_AHB4ENSETR |(0X1<<5);//设置PF9管脚为输入GPIOF->MODER &(~(0x3<<18));//设置PF9管脚为exti9输入EXTI->EXTI…

减小PAPR——DFT扩频

文章目录 前言一、DFT 扩频原理二、MATLAB 仿真1、核心代码2、仿真结果①、4QAM 调制时 IFDMA、LFDMA 和 OFDMA 的 DFT 扩频技术的 PAPR 性能②、16QAM 调制时 IFDMA、LFDMA 和 OFDMA 的 DFT 扩频技术的 PAPR 性能③、64QAM 调制时 IFDMA、LFDMA 和 OFDMA 的 DFT 扩频技术的 PA…

如何在Photoshop中创建色彩鲜艳的文本效果

如何在 Photoshop 中制作霓虹灯 1. 如何创建背景 步骤 1 学习如何在 Photoshop 中制作霓虹灯文本的第一步是背景。创建一个新的 1160 x 750 像素文档&#xff0c;并将分辨率设置为 300。 转到"文件">"嵌入位置"&#xff0c;然后打开"垃圾灰色砖…

tensorrt环境安装-可用于深度学习模型加速推理

安装python环境 在anaconda的命令行中输入conda create --name py38 python3.8 安装python环境 然后安装深度学习框架pytorch环境 Previous PyTorch Versions | PyTorch 在这里面选择合适的环境 conda install pytorch1.8.0 torchvision0.9.0 torchaudio0.8.0 cudatoolki…

汽车项目管理

项目节点&#xff1a; MR (Management Review)——管理层评审 KO (Kick Off)——项目正式启动 SI (Strategy Intent)——战略意图 SC (Strategy Confirmation)——战略确认 PA (Program Approval)——项目批准 PR (Product Readiness)——产品就绪 VP (Verification Prototype)…

kubernetes -pod 实践

一、资源与对象 1、pod 容器都是由镜像启动的,但在容器外面会包裹通过Pod将容器包裹起来这个是K8s的概念,在这个Pod里面可以有一个或多个容器,那这个Pod的有什么特征呢 Pod里的所有容器都会调度在同一个节点上运行0。Pod中的所有容器会共享同一网络,它们有一个唯一的IP,…

leetcode 75. 颜色分类(medium)(优质解法)

链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 代码&#xff1a; class Solution {public void sortColors(int[] nums) {int left-1,rightnums.length,i0;while(i<right){if(nums[i]0){left;swap(nums,left,i);i;}else if(nums…

大师计划1.0 - log2 CRTO笔记

CRTOⅠ笔记 log2 这个笔记是我在2023年11月23日-12月22日中&#xff0c;学习CRTO所做的一些笔记。 事实上TryHackMe的路径和htb学院包含了许多CRTO的知识并且甚至还超出了CRTO&#xff08;CS除外&#xff09;&#xff0c;所以很多东西在THM和htb学院学过&#xff0c;这次CRTO等…

LLM应用于MPC

现有的基于学习的自动驾驶系统&#xff08;AD&#xff09;在理解高级信息和提供可解释性方面存在挑战。为了解决这些问题&#xff0c;这项工作采用LLM作为复杂AD场景的决策组件。作者设计了认知途径&#xff08;cognitive pathway&#xff09;来实现LLM的综合推理&#xff0c;并…

软件接口测试是什么?怎么测?

软件测试是一条超级长的跑道&#xff0c;最好分阶段来跑&#xff1a;先入行&#xff0c;后精通。网上能看到很多软件测试的帖子&#xff0c;但能够准确分类详细介绍的并不多。正好最近有时间&#xff0c;就把我所了解的软件测试做一个小小总结&#xff0c;对你有帮助的话&#…

【100个Cocos实例】环形ScrollView的实现方法

引言 Cocos中环形ScrollView的实现 大家好&#xff0c;今天是圣诞节&#xff0c;又是寒冷的一天。 在游戏开发中经常需要用到ScrollView去实现滚动的列表。 他通常包括垂直方向和水平方向两个选择。 本文将介绍一下ScrollView环形方向的实现。 本文源工程可在文末阅读原文…

ServletContext对象和ServletConfig对象

Servlet几个重要的类的关系图 ServletContext对象 问题&#xff1a; Request解决了一次请求内的数据共享问题&#xff0c;session解决了用户不同请求的数据共享问题&#xff0c;那么不同的用户的数据共享该怎么办呢&#xff1f; 解决&#xff1a;使用ServletContext对象 作…