-
Notifications
You must be signed in to change notification settings - Fork 21
/
qr-scanner.coffee
131 lines (110 loc) · 3.32 KB
/
qr-scanner.coffee
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
qrReactiveDict = new ReactiveDict
@qrScanner =
message: -> qrReactiveDict.get 'message'
on: (eventName, callback) ->
@[eventName] = callback
off: (eventName) ->
delete @[eventName]
imageData: -> ctx.getImageData(0, 0, w, h)
imageDataURL: -> $canvas[0].toDataURL("image/jpeg")
isStarted: -> started
isSupported: -> support
stopCapture: -> stopCapture()
$canvas = null
$video = null
ctx = null
w = null
h = null
localMediaStream = null
localMediaInterval = null
started = false
support = false
showingCanvas = false
Template._qrScanner.rendered = ->
showingCanvas = true
@data?= {}
w = @data.w?= 640
h = @data.h?= 480
$canvas = $('#qr-canvas')
$video = $('#qr-scanner-video')[0]
load()
Template._qrScanner.destroyed = ->
stopCapture()
stopCapture = ->
if localMediaStream
for track in localMediaStream.getTracks()
track.stop()
if localMediaInterval
Meteor.clearInterval localMediaInterval
localMediaInterval = null
showingCanvas = false
qrReactiveDict.set 'message', null
qrScanner.off 'scan'
isCanvasSupported = ->
elem = document.createElement("canvas")
!!(elem.getContext and elem.getContext("2d"))
load = ->
if isCanvasSupported()
initDom()
initWebcam()
else
err = 'Your browser does not support canvas'
console.log err
initDom = ->
$canvas.width(w).attr('width', w)
$canvas.height(h).attr('height', h)
ctx = $canvas[0].getContext("2d")
ctx.clearRect 0, 0, w, h
return
initWebcam = ->
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia
started = true
if navigator.getUserMedia
optional_source = []
# backwards compatability
if MediaStreamTrack.getSources
MediaStreamTrack.getSources (sources) -> parseSources sources
else if navigator.mediaDevices.enumerateDevices
navigator.mediaDevices.enumerateDevices().then (sources) -> parseSources sources
else
support = false
console.log 'Cannot get mediaStream sources'
parseSources = (sourceInfos) ->
for i in [0..sourceInfos.length]
sourceInfo = sourceInfos[i]
if sourceInfo.kind == 'video' && (sourceInfo.facing == '' || sourceInfo.facing == 'environment')\
or sourceInfo.kind == 'videoinput' # for enumerateDevices
optional_source = [sourceId: sourceInfo.id]
break
navigator.getUserMedia
video:
mandatory:
maxWidth: w
maxHeight: h
optional: optional_source
audio: false
, (stream) ->
if navigator.webkitGetUserMedia
$video.src = window.URL.createObjectURL(stream)
else if navigator.mozGetUserMedia
$video.mozSrcObject = stream
$video.play()
else
$video.src = stream
localMediaStream = stream
if !localMediaInterval
localMediaInterval = Meteor.setInterval captureToCanvas, 500
, (err) ->
console.log err
else
support = false
console.log 'Your borwser doesnt support getUserMedia'
captureToCanvas = ->
ctx.drawImage $video, 0, 0
try
message = qrcode.decode()
qrReactiveDict.set 'message', message
if qrScanner.scan then qrScanner.scan null, message
catch
err = "The QR code isnt visible or couldn't be read"
if qrScanner.scan then qrScanner.scan err, null