使用原生JS實(shí)現(xiàn)拍照功能
1. 需求分析
今天我們聊一聊,一個非常有趣且重要的問題,如何用原生js實(shí)現(xiàn)拍照功能?
這時候,有的朋友會說,為什么要用原生js實(shí)現(xiàn)呀,這么麻煩還要自己動腦子,直接用第三方庫多好呀。
說的沒錯,使用第三方庫確實(shí)比較高效。所以,這里我們可以直接考慮使用第三方的js攝像庫,如CameraJS
、WebcamJS
、getUserMediaJS
等,以便更高效地實(shí)現(xiàn)拍照功能。
但是,你難道不好奇它的底層js實(shí)現(xiàn)嗎?也說不定未來某一刻會用到呢,畢竟其靈活性遠(yuǎn)超第三方庫。
一起瞧瞧,原理其實(shí)很簡單。
先明確一下,在項(xiàng)目中啥時候會用到拍照功能呢?
答:拍照功能在許多項(xiàng)目中都可以應(yīng)用,以下是一些常見的需求場景
:
社交媒體應(yīng)用
:社交媒體應(yīng)用通常需要用戶拍攝照片并上傳到平臺上,用于分享、發(fā)布動態(tài)或更改個人資料照片。電子商務(wù)應(yīng)用
:電子商務(wù)應(yīng)用中,可以使用拍照功能讓用戶拍攝商品照片,以便上傳至商品詳情頁或用于售后服務(wù)中。掃描和識別
:拍照功能可以用于掃描和識別文檔、二維碼、條形碼或身份證等信息。例如,應(yīng)用可以使用拍照來掃描身份證,并自動提取身份信息。相機(jī)應(yīng)用和照片編輯
:相機(jī)應(yīng)用需要拍照功能來捕捉照片,同時還可以提供各種照片編輯功能,如濾鏡、裁剪、旋轉(zhuǎn)等。實(shí)時圖像處理
:拍照功能結(jié)合圖像處理技術(shù),可以實(shí)現(xiàn)實(shí)時的圖像濾鏡、人臉識別、美顏等效果。身份驗(yàn)證和安全
:某些應(yīng)用需要拍照以進(jìn)行身份驗(yàn)證或安全認(rèn)證。例如,用戶可以拍攝自己的面部照片,用于人臉識別進(jìn)行登錄或解鎖。文檔管理和歸檔
:拍照功能可以用于文檔管理和歸檔,用戶可以通過拍照將紙質(zhì)文檔轉(zhuǎn)換為電子格式,并進(jìn)行保存和分類。
2. 功能實(shí)現(xiàn)
在明確了上述需求之后,我們正式開始拍照功能的原生js實(shí)現(xiàn),分3步
進(jìn)行吧。我在后面還放了全部的代碼,以及一些需要注意的事項(xiàng)。
2.1 獲取媒體設(shè)備訪問權(quán)限
先檢驗(yàn)使用設(shè)備上是否有媒體設(shè)備,使用 navigator.mediaDevices.
enumerateDevices()
方法。
const navigator = window.navigator.mediaDevices; const devices = await navigator.enumerateDevices(); if (devices) { ... }
再使用 navigator.mediaDevices.getUserMedia()
方法,請求用戶的媒體設(shè)備權(quán)限,包括攝像頭和麥克風(fēng)。該方法會返回視頻流數(shù)據(jù)。
const stream = await navigator.getUserMedia({ audio: false, // 不需要音頻 video: { width: 300, height: 300, // facingMode: { exact: "environment" }, //強(qiáng)制后置攝像頭 facingMode: "user", //前置攝像頭 }, });
2.2 顯示視頻流
將獲取到的視頻流,綁定到HTML的 <video>
元素上,用于實(shí)時顯示攝像頭捕捉的畫面。
if (!videoRef.value) return; videoRef.value.srcObject = stream; videoRef.value.play();
2.3 拍照截圖
通過捕捉 <video>
元素的當(dāng)前畫面,可以實(shí)現(xiàn)拍照功能。你可以使用 <canvas>
元素的drawImage()
方法來繪制視頻畫面,并將其轉(zhuǎn)換為圖像數(shù)據(jù)。
// 設(shè)置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);
最后,你可以將獲取到的圖像數(shù)據(jù),根據(jù)項(xiàng)目具體需求用于后續(xù)的操作
,如顯示、上傳到服務(wù)器等。
2.4 全部代碼
下面是拍照功能實(shí)現(xiàn)的全部代碼
,每行代碼都已做好相應(yīng)注釋,復(fù)制粘貼即可直接使用:
<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(); // 檢驗(yàn)設(shè)備 const checkCamera = async () => { // 先檢驗(yàn)當(dāng)前設(shè)備是否有攝像設(shè)備 const navigator = window.navigator.mediaDevices; const devices = await navigator.enumerateDevices(); // 如果有視頻設(shè)備,則獲取攝像頭 if (devices) { const stream = await navigator.getUserMedia({ audio: false, // 不需要音頻 video: { width: 300, height: 300, // facingMode: { exact: "environment" }, //強(qiáng)制后置攝像頭 facingMode: "user", //前置攝像頭 }, }); console.log(stream); // 用video元素渲染流數(shù)據(jù) if (!videoRef.value) return; videoRef.value.srcObject = stream; videoRef.value.play(); } } // 點(diǎn)擊拍照 const handleShoot = () => { if (!videoRef.value || !wrapperRef.value) return; // 設(shè)置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 一些注意事項(xiàng)
window.navigator.mediaDevices
中的 mediaDevices
屬性,表示了瀏覽器是否支持使用媒體設(shè)備,如攝像頭和麥克風(fēng)。
在某些情況下,這個屬性可能會在某些電腦上存在,而在其他電腦上不存在
。
其原因取決于多個因素,包括瀏覽器的支持程度
、用戶權(quán)限設(shè)置
、網(wǎng)頁的協(xié)議環(huán)境
。如果你在某臺電腦上發(fā)現(xiàn)該屬性不存在,可能是因?yàn)槠渲幸粋€或多個因素導(dǎo)致的。
我在做demo嘗試時,進(jìn)行了網(wǎng)頁的分享,但不是通過 HTTPS 協(xié)議提供的,導(dǎo)致分享設(shè)備瀏覽器被限制了媒體訪問,后面排查了好一段時間。
希望路過的朋友們不要再遇到,腦殼疼!
結(jié)語
以上就是使用原生JS實(shí)現(xiàn)拍照功能的詳細(xì)內(nèi)容,更多關(guān)于JS實(shí)現(xiàn)拍照功能的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript實(shí)現(xiàn)繼承的簡單實(shí)例
這篇文章主要介紹了javascript實(shí)現(xiàn)繼承的簡單實(shí)例的相關(guān)資料,需要的朋友可以參考下2015-07-07bootstrap時間控件daterangepicker使用方法及各種小bug修復(fù)
這篇文章主要介紹了bootstrap時間控件daterangepicker使用方法,及各種小bug修復(fù),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10關(guān)于TypeScript中import JSON的正確姿勢詳解
2012年10月首度對外公布typescript(當(dāng)時已經(jīng)是0.7?的版本)同時開源,ts的編譯器是用js編寫的(后來改成ts?),可以在線編寫。下面這篇文章主要給大家介紹了關(guān)于TypeScript中import JSON的正確姿勢,需要的朋友可以參考下。2017-07-07一文了解JavaScript中call/apply/bind的使用
這篇文章主要介紹了一文了解JavaScript中call/apply/bind的使用,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下2022-07-07bootstarp modal框居中顯示的實(shí)現(xiàn)代碼
這篇文章主要介紹了bootstarp modal框居中顯示的實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-02-02prettier自動格式化去換行的實(shí)現(xiàn)代碼
這篇文章主要介紹了prettier自動格式化去換行的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08location.search在客戶端獲取Url參數(shù)的方法
最近一直在寫html,剛接觸到,感覺挺復(fù)雜的。。比如傳參,在.net里可以直接用Request接受,而在html中還要經(jīng)過處理,找了一些資料,寫了個方法。2010-06-06javascript搜索自動提示功能的實(shí)現(xiàn)
使用 jQuery(Ajax)/PHP/MySQL實(shí)現(xiàn)自動完成功我覺得我有必要寫這個教程,因?yàn)樵?jīng)見到的大部分關(guān)于自動完成的應(yīng)用程序都只是給你一個程序源碼包,然后告訴你怎么使用,而不是告訴你它是如何工作的以及為什么這樣做。2008-06-06