JS打開攝像頭并截圖上傳示例
直入正題,JS打開攝像頭并截圖上傳至后端的一個(gè)完整步驟
1. 打開攝像頭主要用到getUserMedia方法,然后將獲取到的媒體流置入video標(biāo)簽
2. 截取圖片主要用到canvas繪圖,使用drawImage方法將video的內(nèi)容繪至canvas中
3. 將截取的內(nèi)容上傳至服務(wù)器,將canvas中的內(nèi)容轉(zhuǎn)為base64格式上傳,后端(PHP)通過file_put_contents將其轉(zhuǎn)為圖片

要注意的是,在chrome以外的瀏覽器中,使用攝像頭或多或少會(huì)出現(xiàn)一些問題,可能也是老問題了,所以以下代碼主要基于chrome使用
比如在最新版FireFox中的報(bào)錯(cuò),不知為啥


1. 打開攝像頭
getUserMedia 有新版本和舊版本兩種,建議使用新版本
舊版本位于navigator 對(duì)象下,根據(jù)瀏覽器不同有所不同
// 獲取媒體方法(舊方法) navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
if (navigator.getMedia) {
navigator.getMedia({
video: true
}, function(stream) {
mediaStreamTrack = stream.getTracks()[0];
video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}, function(err) {
console.log(err);
});
}
第一個(gè)參數(shù)中指示需要使用視頻(video)或音頻(audio)。
第二個(gè)參數(shù)中指示調(diào)用成功后的回調(diào),其中帶一個(gè)參數(shù)(MediaStream),在舊版本中可以直接通過調(diào)用MediaStream.stop() 來關(guān)閉攝像頭,不過在新版之中已廢棄。需要使用MediaStream.getTracks()[index].stop() 來關(guān)閉相應(yīng)的Track
第三個(gè)參數(shù)指示調(diào)用失敗后的回調(diào)
新版本位于navigator.mediaDevices 對(duì)象下
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function(stream) {
console.log(stream);
mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1];
video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}).catch(function(err) {
console.log(err);
})
}
與舊版類似,不過該方法返回了一個(gè)Promise對(duì)象,可以使用then和catch表示成功與失敗的回調(diào)
需要注意的是,MediaStream.getTracks() 返回的Tracks數(shù)組是按第一個(gè)參數(shù)倒序排列的
比如現(xiàn)在定義了
{
video: true,
audio: true
}
想關(guān)閉攝像頭,就需要調(diào)用MediaStream.getTracks()[1].stop();
同理,0對(duì)應(yīng)于audio的track
使用createObjectURL 將MediaStream寫入video標(biāo)簽,就能夠存儲(chǔ)實(shí)時(shí)的媒體流數(shù)據(jù)(也可以方便的實(shí)時(shí)查看畫面)
舊版本中webkitURL 對(duì)象以不被支持,需要使用URL對(duì)象
<video width="200" height="150"></video>
<canvas width="200" height="150"></canvas>
<p>
<button id="snap">截取圖像</button>
<button id="close">關(guān)閉攝像頭</button>
<button id="upload">上傳圖像</button>
</p>
<img id="uploaded" width="200" height="150" />
2. 截取圖像
將內(nèi)容寫入即可
// 截取圖像
snap.addEventListener('click', function() {
context.drawImage(video, 0, 0, 200, 150);
}, false);
3. 關(guān)閉攝像頭
// 關(guān)閉攝像頭
close.addEventListener('click', function() {
mediaStreamTrack && mediaStreamTrack.stop();
}, false);
4. 上傳截取的圖像
canvas.toDataURL('image/png')
// 上傳截取的圖像
upload.addEventListener('click', function() {
jQuery.post('/uploadSnap.php', {
snapData: canvas.toDataURL('image/png')
}).done(function(rs) {
rs = JSON.parse(rs);
console.log(rs);
uploaded.src = rs.path;
}).fail(function(err) {
console.log(err);
});
}, false);
而這里的后端(PHP)則將獲取的內(nèi)容轉(zhuǎn)換成圖像文件保存
需要注意的是,要將base64的頭部信息字段去掉再保存,否則似乎圖像是損壞無法打開滴
<?php
$snapData = $_POST['snapData'];
$snapData = str_replace('data:image/png;base64,', '', $snapData);
// $snapData = str_replace(' ', '+', $snapData);
$img = base64_decode($snapData);
$uploadDir = 'upload/';
$fileName = date('YmdHis', time()) . uniqid();
if (!(file_put_contents($uploadDir . $fileName, $img))) {
echo json_encode(array('code' => 500, 'msg' => '文件上傳失敗'));
} else {
echo json_encode(array('code' => 200, 'msg' => '文件上傳成功', 'path' => $uploadDir . $fileName));
}
?>
完整JS代碼
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
function $(elem) {
return document.querySelector(elem);
}
// 獲取媒體方法(舊方法)
navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
var canvas = $('canvas'),
context = canvas.getContext('2d'),
video = $('video'),
snap = $('#snap'),
close = $('#close'),
upload = $('#upload'),
uploaded = $('#uploaded'),
mediaStreamTrack;
// 獲取媒體方法(新方法)
// 使用新方法打開攝像頭
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function(stream) {
console.log(stream);
mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1];
video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}).catch(function(err) {
console.log(err);
})
}
// 使用舊方法打開攝像頭
else if (navigator.getMedia) {
navigator.getMedia({
video: true
}, function(stream) {
mediaStreamTrack = stream.getTracks()[0];
video.src = (window.URL || window.webkitURL).createObjectURL(stream);
video.play();
}, function(err) {
console.log(err);
});
}
// 截取圖像
snap.addEventListener('click', function() {
context.drawImage(video, 0, 0, 200, 150);
}, false);
// 關(guān)閉攝像頭
close.addEventListener('click', function() {
mediaStreamTrack && mediaStreamTrack.stop();
}, false);
// 上傳截取的圖像
upload.addEventListener('click', function() {
jQuery.post('/uploadSnap.php', {
snapData: canvas.toDataURL('image/png')
}).done(function(rs) {
rs = JSON.parse(rs);
console.log(rs);
uploaded.src = rs.path;
}).fail(function(err) {
console.log(err);
});
}, false);
</script>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 微信JSSDK實(shí)現(xiàn)打開攝像頭拍照再將相片保存到服務(wù)器
- javascript實(shí)現(xiàn)攝像頭拍照預(yù)覽
- js實(shí)現(xiàn)web調(diào)用攝像頭 js截取視頻畫面
- JS調(diào)用安卓手機(jī)攝像頭掃描二維碼
- js調(diào)用設(shè)備攝像頭的方法
- JS實(shí)現(xiàn)調(diào)用本地?cái)z像頭功能示例
- Vue2.0實(shí)現(xiàn)調(diào)用攝像頭進(jìn)行拍照功能 exif.js實(shí)現(xiàn)圖片上傳功能
- AngularJS中使用HTML5手機(jī)攝像頭拍照
- js+HTML5基于過濾器從攝像頭中捕獲視頻的方法
- JavaScript 如何在瀏覽器中使用攝像頭
相關(guān)文章
JavaScript學(xué)習(xí)筆記之取數(shù)組中最大值和最小值
在實(shí)際業(yè)務(wù)中有的時(shí)候要取出數(shù)組中的最大值或最小值。但在數(shù)組中并沒有提供arr.max()和arr.min()這樣的方法。那么是不是可以通過別的方式實(shí)現(xiàn)類似這樣的方法呢?那么今天我們就來整理取出數(shù)組中最大值和最小值的一些方法,需要的朋友一起學(xué)習(xí)吧2016-03-03
自己做的模擬模態(tài)對(duì)話框?qū)崿F(xiàn)代碼
最近做完一個(gè)項(xiàng)目,發(fā)現(xiàn)瀏覽器兼容問題,模態(tài)對(duì)話框只有IE支持,但是IE9又不能支持帶框架的對(duì)話框,那個(gè)對(duì)話框的大小打死都設(shè)置不了,在網(wǎng)上查說因?yàn)楹枚喙δ鼙籌E9屏蔽了,于是自己做了一個(gè)模擬對(duì)話框的東西2012-05-05
簡(jiǎn)單了解JavaScript中的執(zhí)行上下文和堆棧
這篇文章主要介紹了簡(jiǎn)單了解JavaScript中的執(zhí)行上下文和堆棧,你應(yīng)該對(duì)解釋器了解得更清楚:為什么在聲明它們之前可以使用某些函數(shù)或變量?以及它們的值是如何確定的?,需要的朋友可以參考下2019-06-06
用JavaScript實(shí)現(xiàn)類似于ListBox功能示例代碼
這篇文章主要介紹了用JavaScript實(shí)現(xiàn)類似于ListBox功能,需要的朋友可以參考下2014-03-03
nodejs創(chuàng)建web服務(wù)器之hello world程序
本文給大家分享nodejs創(chuàng)建web服務(wù)器之hello world程序,node真的很好用,不僅用v8引擎來解析了javascript外,還提供了高度優(yōu)化的應(yīng)用庫,真的很好,有需要的朋友一起來學(xué)習(xí)吧2015-08-08
詳解原生JavaScript實(shí)現(xiàn)jQuery中AJAX處理的方法
這篇文章主要介紹了原生JavaScript實(shí)現(xiàn)jQuery中AJAX處理的方法,作者根據(jù)jQuery中一些對(duì)AJAX請(qǐng)求的處理方式來用原生API實(shí)現(xiàn),需要的朋友可以參考下2016-05-05
JS正則表達(dá)式驗(yàn)證端口范圍(0-65535)
這篇文章主要介紹了JS正則表達(dá)式驗(yàn)證端口范圍(0-65535),文中給大家提到了Js正則表達(dá)式驗(yàn)證IP+端口號(hào)的代碼,需要的朋友可以參考下2020-01-01

