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

2023-12-27 00:06:40

大家好,我是大澈!

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

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

结语

建立这个平台的初衷:

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

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

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

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

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

文章来源:https://blog.csdn.net/m0_74802419/article/details/135233337
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。