JavaScriptでバーコードを読み取る方法

利用ライブラリ

利用ライブラリ
https://github.com/ericblade/quagga2

※元々はhttps://github.com/serratus/quaggaJS の方ですが保守されていないのでフォークされた上の方が良いです

コード

html

1
2
3
4
5
<button type="button" class="btn btn-fab btn-round btn-info btc_scan" name="btc_scan"></button>
<!-- スキャンエリア -->
<div class="scan_area" style="height: 100vh; display:none">
<div id="photo-area" class="viewport"></div>
</div>

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
// スキャン
function register_btc_scan() {
$('.btc_scan').on('click', (event) => {
$('.scan_area').show()
startScanner()
scrollTo(0, 0)
})
const startScanner = () => {
Quagga.init(
{
inputStream: {
numOfWorkers: 0,
frequency: 1,
name: 'Live',
type: 'LiveStream',
target: document.querySelector('#photo-area'),
constraints: {
decodeBarCodeRate: 3,
successTimeout: 500,
codeRepetition: false,
tryVertical: true,
frameRate: 15,
facingMode: 'environment',
},
},
decoder: {
readers: ['ean_reader'],
},
},
function (err) {
if (err) {
console.log(err)
return
}
console.log('Initialization finished. Ready to start')
Quagga.start()
_scannerIsRunning = true
}
)
Quagga.onProcessed(_onProcessed)
Quagga.onDetected(_onDetected)
}
}
// スキャン中
function _onProcessed(result) {
var drawingCtx = Quagga.canvas.ctx.overlay,
drawingCanvas = Quagga.canvas.dom.overlay
if (result) {
if (result.boxes) {
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute('width')), parseInt(drawingCanvas.getAttribute('height')))
result.boxes
.filter(function (box) {
return box !== result.box
})
.forEach(function (box) {
Quagga.ImageDebug.drawPath(
box,
{
x: 0,
y: 1,
},
drawingCtx,
{
color: 'green',
lineWidth: 2,
}
)
})
}
if (result.box) {
Quagga.ImageDebug.drawPath(
result.box,
{
x: 0,
y: 1,
},
drawingCtx,
{
color: '#00F',
lineWidth: 2,
}
)
}
if (result.codeResult && result.codeResult.code) {
Quagga.ImageDebug.drawPath(
result.line,
{
x: 'x',
y: 'y',
},
drawingCtx,
{
color: 'red',
lineWidth: 3,
}
)
}
}
}

function _getMedian(arr) {
arr.sort((a, b) => a - b)
const half = Math.floor(arr.length / 2)
if (arr.length % 2 === 1)
// Odd length
return arr[half]
return (arr[half - 1] + arr[half]) / 2.0
}

let codes = []

// 検知した
function _onDetected(result) {
// 1つでもエラー率0.16以上があれば除外
let is_err = false
$.each(result.codeResult.decodedCodes, function (id, error) {
if (error.error != undefined) {
if (parseFloat(error.error) > 0.16) {
is_err = true
}
}
})
if (is_err) return

// エラー率のmedianが0.05以上なら除外
const errors = result.codeResult.decodedCodes.filter((_) => _.error !== undefined).map((_) => _.error)
const median = _getMedian(errors)
if (median > 0.05) {
return
}

// 3連続同じ数値だった場合のみ採用する
codes.push(result.codeResult.code)
if (codes.length < 3) return
let is_same_all = false
if (codes.every((v) => v === codes[0])) {
is_same_all = true
}
if (!is_same_all) {
codes.shift()
return
}

alert(result.codeResult.code)
$('.scan_area').hide()
Quagga.stop()
Quagga.offProcessed(_onProcessed)
Quagga.offDetected(_onDetected)
}

そのままだと画面いっぱいのサイズにならないので以下を追加して画面いっぱいのサイズになるようにしました
無理やり感ありますが、、

1
2
3
4
5
6
7
8
#photo-area.viewport video {
transform: translateX(-20vw) translateY(-30vw);
width: 120vw;
}

#photo-area.viewport canvas {
transform: translateX(-20vw) translateY(-200vw);
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×