You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.6 KiB
102 lines
2.6 KiB
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Document</title>
|
|
</head>
|
|
<body>
|
|
<video id="video" autoplay muted playsinline></video>
|
|
</body>
|
|
<script type="module">
|
|
import BarcodeDetector from "https://cdn.skypack.dev/barcode-detector@0.5.0";
|
|
|
|
const adaptOldFormat = detectedCodes => {
|
|
if (detectedCodes.length > 0) {
|
|
const [ firstCode ] = detectedCodes;
|
|
|
|
const [
|
|
topLeftCorner,
|
|
topRightCorner,
|
|
bottomRightCorner,
|
|
bottomLeftCorner
|
|
] = firstCode.cornerPoints
|
|
|
|
return {
|
|
content: firstCode.rawValue,
|
|
location: {
|
|
topLeftCorner,
|
|
topRightCorner,
|
|
bottomRightCorner,
|
|
bottomLeftCorner,
|
|
|
|
// not supported by native API:
|
|
topLeftFinderPattern: {},
|
|
topRightFinderPattern: {},
|
|
bottomLeftFinderPattern: {}
|
|
},
|
|
imageData: null
|
|
}
|
|
} else {
|
|
return {
|
|
content: null,
|
|
location: null,
|
|
imageData: null
|
|
}
|
|
}
|
|
}
|
|
|
|
export const keepScanning = (videoElement, options) => {
|
|
const barcodeDetector = new BarcodeDetector({ formats: ["qr_code"] });
|
|
|
|
const { detectHandler, locateHandler, minDelay } = options;
|
|
|
|
const processFrame = state => async timeNow => {
|
|
if (videoElement.readyState > 1) {
|
|
console.log("scan")
|
|
const { lastScanned, contentBefore, locationBefore } = state
|
|
|
|
if (timeNow - lastScanned >= minDelay) {
|
|
const detectedCodes = await barcodeDetector.detect(videoElement);
|
|
const { content, location, imageData } = adaptOldFormat(detectedCodes)
|
|
|
|
if (content !== null && content !== contentBefore) {
|
|
detectHandler({ content, location, imageData });
|
|
}
|
|
|
|
if (location !== null || locationBefore !== null) {
|
|
locateHandler(detectedCodes);
|
|
}
|
|
|
|
window.requestAnimationFrame(processFrame({
|
|
lastScanned: timeNow,
|
|
contentBefore: content ?? contentBefore,
|
|
locationBefore: location
|
|
}))
|
|
} else {
|
|
window.requestAnimationFrame(processFrame(state))
|
|
}
|
|
}
|
|
};
|
|
|
|
processFrame({
|
|
contentBefore: null,
|
|
locationBefore: null,
|
|
lastScanned: performance.now()
|
|
})();
|
|
};
|
|
|
|
(async () => {
|
|
const videoEl = document.querySelector('#video')
|
|
|
|
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false })
|
|
|
|
videoEl.srcObject = stream
|
|
|
|
videoEl.addEventListener("loadeddata", () => {
|
|
keepScanning(videoEl, { minDelay: 40, detectHandler: console.log, locateHandler: console.log })
|
|
})
|
|
|
|
})()
|
|
</script>
|
|
</html>
|
|
|