思路
第一步: 要能調(diào)起設(shè)備攝像頭
第二步:掃碼
第三步:解析二維碼
技術(shù)簡介
WebRTC API
WebRTC (Web Real-Time Communications)
是一項實時通訊技術(shù),它允許網(wǎng)絡(luò)應(yīng)用或者站點,在不借助中間媒介的情況下,建立瀏覽器之間 點對點(Peer-to-Peer)
的連接,實現(xiàn)視頻流和(或)音頻流或者其他任意數(shù)據(jù)的傳輸。WebRTC
包含的這些標準使用戶在無需安裝任何插件或者第三方的軟件的情況下,創(chuàng)建 點對點(Peer-to-Peer)
的數(shù)據(jù)分享和電話會議成為可能。
重要接口
MediaStream
接口:是一個媒體內(nèi)容的流.。一個流包含幾個軌道,比如視頻和音頻軌道。
MDN : WebRTC API
核心的API navigator.mediaDevices.getUserMedia
MediaDevices
接口提供訪問連接媒體輸入的設(shè)備,如照相機和麥克風,以及屏幕共享等。它可以使你取得任何硬件資源的媒體數(shù)據(jù)。
MediaDevices.getUserMedia()
會提示用戶給予使用媒體輸入的許可,媒體輸入會產(chǎn)生一個MediaStream,里面包含了請求的媒體類型的軌道。此流可以包含一個視頻軌道(來自硬件或者虛擬視頻源,比如相機、視頻采集設(shè)備和屏幕共享服務(wù)等等)、一個音頻軌道(同樣來自硬件或虛擬音頻源,比如麥克風、A/D 轉(zhuǎn)換器等等),也可能是其它軌道類型。
它返回一個 Promise 對象,成功后會resolve回調(diào)一個 MediaStream
對象。若用戶拒絕了使用權(quán)限,或者需要的媒體源不可用,promise會reject回調(diào)一個 PermissionDeniedError
或者 NotFoundError
。
通常你可以使用 navigator.mediaDevices
來獲取 MediaDevices
,例如:
navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
/* 使用這個 stream stream */
})
.catch(function(err) {
/* 處理 error */
});
語法
var promise = navigator.mediaDevices.getUserMedia(constraints);
以下同時請求不帶任何參數(shù)的音頻和視頻:
MDN: MediaDevices
二維碼解析庫 JSQR
jsQR 是一個純 JavaScript 二維碼解析庫,該庫讀取原始圖像或者是攝像頭,并將定位,提取和解析其中的任何 QR碼。
如果要使用 jsQR 掃描網(wǎng)絡(luò)攝像頭流,則需要 ImageData 從視頻流中提取,然后可以將其傳遞給 jsQR。
jsQR 導(dǎo)出一個方法,該方法接受 4 個參數(shù),分別是解碼的 圖像數(shù)據(jù),寬、高 以及 可選的對象 進一步配置掃描行為。
imageData:格式為 [r0, g0, b0, a0, r1, g1, b1, a1, …] 的 Uint8ClampedArray( 8位無符號整型固定數(shù)組) 的 rgba 像素值。
const code = jsQR(imageData, width, height, options);
if (code) {
console.log('找到二維碼!', code);
}
github:jsQR
requestAnimationFrame
window.requestAnimationFrame()
告訴瀏覽器——你希望執(zhí)行一個動畫,并且要求瀏覽器在下次重繪之前調(diào)用指定的回調(diào)函數(shù)更新動畫。該方法需要傳入一個回調(diào)函數(shù)作為參數(shù),該回調(diào)函數(shù)會在瀏覽器下一次重繪之前執(zhí)行.
window.requestAnimationFrame(callback);
MDN: requestAnimationFrame
代碼實現(xiàn)
流程: 瀏覽器進行調(diào)取攝像頭,調(diào)用失敗執(zhí)行失敗的回調(diào);調(diào)用成功,進行捕獲視頻流,然后掃碼識別,沒有掃描到二維碼就繼續(xù)掃描, 掃碼成功之后彈出掃碼內(nèi)容, 并停止掃碼。
初始化
<div></div>
<video src="" style="display: none"></video>
<canvas></canvas>
// 捕獲視頻流
var promise = navigator.mediaDevices.getUserMedia({ video: true })
promise.then((mediaStream) => {
// 成功的返回值mediaStream,既是媒體內(nèi)容的流。
// 通過原生video標簽,展示視頻
document.querySelector('video').srcObject = mediaStream
document.querySelector('video').play()
// 調(diào)用tick之前, 這個時候已經(jīng)可以看到頁面上在展示我們錄制到的內(nèi)容
tick()
}).catch(function (err) {
console.log(err, 'err')
})
// tick方法,初始化canvas,調(diào)用jsQR識別二維碼
function tick() {
let cvs = document.querySelector('canvas')
var ctx = cvs.getContext('2d')
cvs.width = '800'
cvs.height = '600'
// 通過canvas繪制每一幀圖片, 使繪制的圖片和video展示的圖片相吻合
ctx.drawImage(document.querySelector('video'), 0, 0, '800', '600')
// 獲取畫布數(shù)據(jù)(存儲像素點信息)
const imageData = ctx.getImageData(0, 0, '800', '600')
let code = false
// jsQR 識別二維碼
code = jsQR(imageData.data, imageData.width, imageData.height)
if (code) {
// 找到二維碼,并展示在頁面上
document.querySelector('div').innerHTML = code.data
// 繪制矩形框
drawBox(code.location)
}
// 這次沒有找到二維碼,調(diào)用run方法
run()
}
function run() {
if (!document.querySelector('div').innerHTML) {
// 進行周期性掃碼識別
requestAnimationFrame(tick)
}
}
可以看下, 這是掃碼成功的回調(diào)。location
對象里包含了二維碼具體的位置, 我們可以通過canvas
劃線,把頁面中的碼位置圈出來
function drawBox(location) {
drawLine(location.topLeftCorner, location.topRightCorner)
drawLine(location.topRightCorner, location.bottomRightCorner)
drawLine(location.bottomRightCorner, location.bottomLeftCorner)
drawLine(location.bottomLeftCorner, location.topLeftCorner)
}
function drawLine(begin, end) {
let cvs = document.querySelector('canvas')
var ctx = cvs.getContext('2d')
ctx.beginPath()
ctx.moveTo(begin.x, begin.y)
ctx.lineTo(end.x, end.y)
ctx.lineWidth = '3'
ctx.strokeStyle = 'red'
ctx.stroke()
}
最終實現(xiàn)效果就是這樣
到這里基本上就完事了, 可以調(diào)起攝像頭, 可以正確掃碼并拿到對應(yīng)的值。文章來源:http://www.zghlxwxcb.cn/news/detail-457935.html
參考文章: https://github.com/dragonir/h5-scan-qrcode
JSQR: https://www.npmjs.com/package/jsqr
https://blog.csdn.net/weixin_41856395/article/details/120597131文章來源地址http://www.zghlxwxcb.cn/news/detail-457935.html
到了這里,關(guān)于H5調(diào)用攝像頭掃碼詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!