forked from fletcherrippon/JavaScriptQRCodeReader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
150 lines (121 loc) · 4.27 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
let codes = [];
const seen = new Set();
// Create new barcode detector
const barcodeDetector = new BarcodeDetector({ formats: ['qr_code'] });
// Define custom element
customElements.define('scaned-item', class extends HTMLElement {
constructor() {
super();
const template = document.querySelector('#scaned-item').content;
const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(template.cloneNode(true));
};
});
// Codes proxy/state
const codesProxy = new Proxy(codes, {
set (target, prop, value, receiver) {
// Throw err if value is a number
// Stops from saving undefined codes
if (typeof value === 'number') throw value;
target.push(value);
// Check if code has already been scanned
target = target.filter((c) => {
if (c.rawValue !== window.barcodeVal) return c;
const d = seen.has(c.rawValue);
seen.add(c.rawValue);
return !d;
})
// Select the container scanned
const scanned = document.querySelector('#scanned')
const temp = document.createElement('scaned-item')
const format = document.createElement('span')
const rawValue = document.createElement('span')
// Goes into the custom elements formate slot
format.setAttribute('slot', 'format');
format.innerHTML = value.format;
// Goes into the custom elements raw slot
rawValue.setAttribute('slot', 'raw');
rawValue.innerHTML = value.rawValue;
// Append elements to custom element
temp.appendChild(rawValue);
temp.appendChild(format);
// Append Custom element to scanned container
scanned.appendChild(temp);
return true;
}
});
// Get video element
const video = document.getElementById('video');
// Check for a camera
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
const constraints = {
video: true,
audio: false
};
// Start video stream
navigator.mediaDevices.getUserMedia(constraints).then(stream => video.srcObject = stream);
}
// Draw outline to canvas
/* --NOTE--
Some codes will not out line the whole barcode
instead may have a thin line this is because for a lot of
barcodes that is all that is needed.
if you would like to out line the whole code you can have
a look at using the boundingBox object instead of
the cornerPoints array in this example it is not used
but my edit this to make a square around other codes
that do not get outlined :)
*/
const drawCodePath = ({cornerPoints}) => {
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
const strokeGradient = ctx.createLinearGradient(0, 0, canvas.scrollWidth, canvas.scrollHeight);
// Exit function and clear canvas if no corner points
if (!cornerPoints) return ctx.clearRect(0, 0, canvas.width, canvas.height);
// Clear canvas for new redraw
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Create new gradient
strokeGradient.addColorStop('0', '#c471ed');
strokeGradient.addColorStop('1', '#f7797d');
// Define stoke styles
ctx.strokeStyle = strokeGradient;
ctx.lineWidth = 4;
// Begin draw
ctx.beginPath();
// Draw code outline path
for (const [i, {x, y}] of cornerPoints.entries()) {
if (i === 0) {
// Move x half of the stroke width back
// makes the start and end corner line up
ctx.moveTo(x - ctx.lineWidth/2, y);
continue;
}
// Draw line from current pos to x, y
ctx.lineTo(x, y);
// Complete square draw to starting position
if (i === cornerPoints.length-1) ctx.lineTo(cornerPoints[0].x, cornerPoints[0].y);
}
// Make path to stroke
ctx.stroke();
}
// Detect code function
const detectCode = () => {
barcodeDetector.detect(video).then(codes => {
// If no codes exit function and clear canvas
if (codes.length === 0) return drawCodePath({});
for (const barcode of codes) {
console.log(barcode)
// Draw outline
drawCodePath(barcode);
// Code in seen set then exit loop
if (seen.has(barcode.rawValue)) return;
// Save barcode to window to use later on
// then push to the codes proxy
window.barcodeVal = barcode.rawValue;
codesProxy.push(barcode);
}
}).catch(err => {
console.error(err);
})
}
// Run detect code function every 100 milliseconds
setInterval(detectCode, 100);