33 < link rel ="stylesheet " href ="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css "
44 integrity ="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T " crossorigin ="anonymous ">
55
6+ < meta name ="viewport " content ="width=device-width, initial-scale=1 ">
7+
68 < style >
79 .loader {
8- border : 16 px solid # f3f3f3 ;
10+ border : 5 vw solid # f3f3f3 ;
911 border-radius : 50% ;
10- border-top : 16 px solid # 3498db ;
11- width : 120 px ;
12- height : 120 px ;
12+ border-top : 5 vw solid # 3498db ;
13+ width : 20 vw ;
14+ height : 20 vw ;
1315 -webkit-animation : spin 2s linear infinite;
1416 /* Safari */
1517 animation : spin 2s linear infinite;
8385 text-decoration : none;
8486 cursor : pointer;
8587 }
88+
89+ .fit-screen {
90+ max-width : 100% ;
91+ max-height : 100% ;
92+ bottom : 0 ;
93+ left : 0 ;
94+ right : 0 ;
95+ top : 0 ;
96+ -o-object-fit : contain;
97+ object-fit : contain;
98+ }
8699 </ style >
87100</ head >
88101
89102< body >
90103 < p id ="desc "> </ p >
91104 < div id ="acuant-loader " class ="row text-center " style ="display:none; ">
92105 < div class ="col-md-12 ">
93- < div class ="loader " style ="margin: 10% 0 0 45% "> </ div >
106+ < div class ="loader " style ="margin: 20% auto 0 auto "> </ div >
94107 </ div >
95108 </ div >
96109 < div id ="camera-btn " class ="row text-center " style ="display:none; margin:10% 0 10% 0 ">
99112 < button class ="btn btn-success mr-2 " onClick ="openCamera() "> Open Camera</ button >
100113 </ div >
101114 </ div >
102- < div id ="camera " style ="display:none; ">
103- < video id ="acuant-player " controls autoplay style ="display:none; " playsinline > </ video >
104- < div class ="row ">
105- < div class ="col-md-12 text-center ">
106- < canvas id ="acuant-video-canvas " width ="100% " height ="auto "> </ canvas >
107- </ div >
115+ < div class ="row ">
116+ < div class ="col-md-12 text-center ">
117+ < div id ="acuant-camera "> </ div >
108118 </ div >
109119 </ div >
110120 < div id ="result-face " style ="display:none; ">
128138 < div id ="result-id " style ="display:none ">
129139 < div class ="row text-center ">
130140 < div class ="col-md-12 ">
131- < canvas id ="result-canvas " width =" auto " height =" auto "> </ canvas >
141+ < canvas id ="result-id-img " class =" fit-screen " style =" display:block "> </ canvas >
132142 </ div >
133143 </ div >
134144 < div class ="row text-center " style ="margin-top:1% ">
150160 < div id ="acuant-modal " class ="modal-content " style ="display: none; margin-top:30% ">
151161 < span class ="close "> ×</ span >
152162 < div class ="row " style ="margin:3% ">
153- < h3 > Live Camera failed to open. Start manual capture </ h3 >
163+ < h3 id =" acuant-modal-text " > </ h3 >
154164 </ div >
155165 < div class ="row text-right " style ="margin:3% ">
156166 < button class ="btn btn-success mr-2 " onClick ="startManualCapture() "> Start Manual Capture</ button >
@@ -169,20 +179,17 @@ <h3>Live Camera failed to open. Start manual capture</h3>
169179 acas_endpoint : "https://acas.acuant.net" ,
170180 liveness_endpoint :"https://us.passlive.acuant.net"
171181 }
172- const player = document . getElementById ( 'acuant-player' ) ;
173182
174- const videoCanvas = document . getElementById ( 'acuant-video-canvas' ) ;
175- const videoContext = videoCanvas . getContext ( '2d' ) ;
183+ const player = document . getElementById ( 'acuant-player' ) ;
176184
177185 const cameraBtn = document . getElementById ( 'camera-btn' ) ;
178- const camera = document . getElementById ( 'camera' ) ;
186+ const camera = document . getElementById ( 'acuant- camera' ) ;
179187 const desc = document . getElementById ( 'desc' ) ;
180188 const result = document . getElementById ( 'result-id' ) ;
181189
182190 const resultFace = document . getElementById ( 'result-face' ) ;
183191
184- const canvas = document . getElementById ( 'result-canvas' ) ;
185- const context = canvas . getContext ( '2d' ) ;
192+ const resultId = document . getElementById ( 'result-id-img' ) ;
186193
187194 const sharpnessInput = document . getElementById ( 'sharpness' ) ;
188195 const glareInput = document . getElementById ( 'glare' ) ;
@@ -194,6 +201,9 @@ <h3>Live Camera failed to open. Start manual capture</h3>
194201 var currentResult = { } ;
195202
196203 function onAcuantSdkLoaded ( ) {
204+ //Unexpected errors shouldn't happen with correct usage of the sdk, and should be fine to leave out,
205+ //but to be safe you can handle it with a callback function like this:
206+ AcuantJavascriptWebSdk . setUnexpectedErrorCallback ( unexpectedError ) ;
197207 init ( ) ;
198208 }
199209
@@ -202,15 +212,28 @@ <h3>Live Camera failed to open. Start manual capture</h3>
202212 //alternatively AcuantJavascriptWebSdk.initializeWithToken replacing base64Token with the oauth token leaving the rest the same
203213 AcuantJavascriptWebSdk . initialize ( base64Token , Credential . acas_endpoint , {
204214 onSuccess : function ( ) {
205- showCameraButton ( ) ;
206- console . log ( "intialize succeded" ) ;
215+ if ( ! isOldiOS ( ) ) {
216+ AcuantJavascriptWebSdk . startWorkers ( initDone ) ; //no list of workers to start means it will start all the workers.
217+ } else {
218+ AcuantJavascriptWebSdk . startWorkers ( initDone , [ AcuantJavascriptWebSdk . ACUANT_IMAGE_WORKER ] ) ; //old ios devices can struggle running metrics. See readme for more info.
219+ }
207220 } ,
208221 onFail : function ( code , description ) {
209- console . log ( "intialize failed " + code + ": " + description ) ;
222+ console . log ( "initialize failed " + code + ": " + description ) ;
210223 }
211224 } ) ;
212225 }
213226
227+ //Good practice to end workers when you are done with them (does not have to be in onbeforeunload, end them when you are done with them in your workflow and won't use them again).
228+ window . onbeforeunload = function ( event ) {
229+ end ( ) ;
230+ } ;
231+
232+ function initDone ( ) {
233+ showCameraButton ( ) ;
234+ console . log ( "initialize succeded" ) ;
235+ }
236+
214237 function showCameraButton ( ) {
215238 cameraBtn . style . display = "block" ;
216239 }
@@ -219,7 +242,7 @@ <h3>Live Camera failed to open. Start manual capture</h3>
219242 camera . style . display = "none" ;
220243 result . style . display = "block" ;
221244 cameraBtn . style . display = "block" ;
222- desc . style . display = "block"
245+ desc . style . display = "block" ;
223246 }
224247
225248 function openCamera ( ) {
@@ -242,83 +265,88 @@ <h3>Live Camera failed to open. Start manual capture</h3>
242265 }
243266
244267 var cameraCallback = {
245- onCaptured : function ( response ) {
246- loader . style . display = "block" ;
247- camera . style . display = "none" ;
248- } ,
249- onCropped : function ( response ) {
250- if ( response ) {
251- drawImageOnResult ( response ) ;
252- }
253- closeCamera ( ) ;
254- loader . style . display = "none" ;
255- } ,
268+ onCaptured : onCaptured ,
269+ onCropped : onCropped ,
256270 onFrameAvailable : function ( response ) {
257271 //get each frame if needed
258272 //console.log(response)
259273 }
260274 }
261275
262276 function startCamera ( ) {
277+ currentResult = { } ;
263278 if ( AcuantCamera . isCameraSupported && ! AcuantCamera . isIOSWebview && ! liveCaptureFailed ) {
264279 cameraBtn . style . display = "none" ;
265280 camera . style . display = "block" ;
266281
267- AcuantCameraUI . start ( cameraCallback , ( error ) => {
268- modal . style . display = "block" ;
269- camera . style . display = "none" ;
270- liveCaptureFailed = true ;
271- } , options ) ;
282+ AcuantCameraUI . start ( cameraCallback , onError , options ) ;
272283 }
273284 else {
274285 startManualCapture ( )
275286 }
276287 }
277288
278- function startManualCapture ( ) {
279- AcuantCamera . startManualCapture ( {
280- onCropped : function ( response ) {
281- loader . style . display = "none" ;
282-
283- if ( response ) {
284- closeCamera ( ) ;
285- drawImageOnResult ( response ) ;
286- }
287- else {
288- closeCamera ( ) ;
289- }
290- } ,
291- onCaptured : function ( response ) {
292- cameraBtn . style . display = "none" ;
293- modal . style . display = "none" ;
294- loader . style . display = "block" ;
289+ function onError ( error , code ) {
290+ camera . style . display = "none" ;
291+ console . error ( error , code ) ;
292+ liveCaptureFailed = true ;
293+
294+ if ( code === AcuantJavascriptWebSdk . REPEAT_FAIL_CODE ) { //live capture was started after previous failure leading to manual capture, show any elements you may have hidden as the user can cancel the prompt and could otherwise end up on a blank page.
295+ cameraBtn . style . display = "block" ;
296+ } else {
297+ modal . style . display = "block" ;
298+ switch ( code ) {
299+ case AcuantJavascriptWebSdk . SEQUENCE_BREAK_CODE : //ios 15 bug
300+ modalText . innerHTML = "Camera failed due to ios 15 bug. Start manual capture." ;
301+ break ;
302+ case AcuantJavascriptWebSdk . START_FAIL_CODE : //camera not supported or permission not granted
303+ modalText . innerHTML = "Live Camera failed to open. Start manual capture." ;
304+ break ;
305+ default : //unknown error (shouldn't happen)
306+ modalText . innerHTML = "Unknown camera failure. Start manual capture." ;
307+ break ;
295308 }
296- } ) ;
309+ }
310+ }
311+
312+ function onCaptured ( response ) {
313+ cameraBtn . style . display = "none" ;
314+ modal . style . display = "none" ;
315+ loader . style . display = "block" ;
316+ }
317+
318+ function onCropped ( response ) {
319+ if ( response ) {
320+ drawImageOnResult ( response ) ;
321+ }
322+ closeCamera ( ) ;
323+ loader . style . display = "none" ;
324+ }
325+
326+ function startManualCapture ( ) {
327+ AcuantCamera . startManualCapture ( cameraCallback ) ;
297328 }
298329
299330 function end ( ) {
300- AcuantJavascriptWebSdk . end ( ) ;
331+ AcuantJavascriptWebSdk . endWorkers ( ) ;
301332 }
302333
303334 function drawImageOnResult ( result ) {
304335 if ( result && result . image ) {
305- var image = new Image ( ) ;
306- image . onload = function ( ) {
307- let width = result . image . width ;
308- let height = result . image . height ;
309-
310- sharpnessInput . value = result . sharpness ;
311- glareInput . value = result . glare ;
312- dpiInput . value = result . dpi ;
313-
314- canvas . width = width ;
315- canvas . height = height ;
316- context . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
317- context . drawImage ( image , 0 , 0 , canvas . width , canvas . height ) ;
318- window . scrollTo ( 0 , window . screen . height ) ;
319- } ;
320- image . src = result . image . data ;
321336 currentResult = result . image . data ;
337+
338+ resultId . width = result . image . width ;
339+ resultId . height = result . image . height ;
340+
341+ const imgContext = resultId . getContext ( '2d' ) ;
342+ const imgBuffer = imgContext . createImageData ( result . image . width , result . image . height ) ;
343+ imgBuffer . data . set ( result . image . bytes , 0 ) ;
344+
345+ imgContext . putImageData ( imgBuffer , 0 , 0 ) ;
346+
347+ sharpnessInput . value = result . sharpness ;
348+ glareInput . value = result . glare ;
349+ dpiInput . value = result . dpi ;
322350 }
323351 }
324352
@@ -332,6 +360,30 @@ <h3>Live Camera failed to open. Start manual capture</h3>
332360 link . click ( ) ;
333361 }
334362
363+ //this is an example of how to detect an older ios device.
364+ //depending on your enviroment you might be able to get more specific.
365+ function isOldiOS ( ) {
366+ let keyPhrase = "iPhone OS" ;
367+ let ua = navigator . userAgent ;
368+ let index = ua . indexOf ( keyPhrase ) ;
369+ if ( index > 0 ) {
370+ let version = ua . substring ( index + keyPhrase . length + 1 , index + keyPhrase . length + 3 ) ;
371+ let versionNum = parseInt ( version ) ;
372+ if ( versionNum && versionNum < 13 ) {
373+ return true ;
374+ } else {
375+ return false ;
376+ }
377+ } else {
378+ return false ;
379+ }
380+ }
381+
382+ function unexpectedError ( errorMsg ) {
383+ //handle an unexpected or unknown error
384+ console . error ( "Got an unexpected error callback:" , errorMsg ) ;
385+ }
386+
335387 //**************** Passive Liveness==========================
336388
337389 function setUIValues ( id , value ) {
@@ -373,7 +425,8 @@ <h3>Live Camera failed to open. Start manual capture</h3>
373425
374426 //**************** Custom Modal===========================
375427 // Get the modal
376- var modal = document . getElementById ( "acuant-modal" ) ;
428+ const modal = document . getElementById ( "acuant-modal" ) ;
429+ const modalText = document . getElementById ( 'acuant-modal-text' ) ;
377430
378431 // Get the <span> element that closes the modal
379432 var span = document . getElementsByClassName ( "close" ) [ 0 ] ;
@@ -399,6 +452,9 @@ <h3>Live Camera failed to open. Start manual capture</h3>
399452 jpegQuality : 1.0 //strongly advised not to modify (can be left out will default to 1.0)
400453 }
401454</ script >
402- < script async src ="/webSdk/dist/AcuantJavascriptWebSdk.min.js " charset ="utf-8 "> </ script >
455+ < script src ="/app/Credential.js "> </ script >
456+ < script src ="/webSdk/dist/AcuantJavascriptWebSdk.min.js " charset ="utf-8 "> </ script >
457+ < script async src ="/webSdk/dist/AcuantCamera.min.js " charset ="utf-8 "> </ script >
458+ < script async src ="/webSdk/dist/AcuantPassiveLiveness.min.js " charset ="utf-8 "> </ script >
403459
404- </ html >
460+ </ html >
0 commit comments