remote-calibrator 0.3.0-rc.3 → 0.5.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +35 -3
  2. package/README.md +34 -49
  3. package/homepage/example.css +4 -3
  4. package/homepage/example.js +42 -22
  5. package/homepage/index.html +19 -4
  6. package/i18n/fetch-languages-sheets.js +11 -1
  7. package/lib/RemoteCalibrator.min.js +1 -1
  8. package/lib/RemoteCalibrator.min.js.LICENSE.txt +19 -2
  9. package/lib/RemoteCalibrator.min.js.map +1 -1
  10. package/netlify.toml +1 -1
  11. package/package.json +25 -24
  12. package/src/WebGazer4RC/package-lock.json +198 -143
  13. package/src/WebGazer4RC/package.json +2 -2
  14. package/src/WebGazer4RC/src/index.mjs +161 -52
  15. package/src/WebGazer4RC/test/webgazer_test.js +1 -1
  16. package/src/check/checkScreenSize.js +84 -0
  17. package/src/components/buttons.js +21 -4
  18. package/src/components/input.js +82 -0
  19. package/src/components/keyBinder.js +5 -6
  20. package/src/components/language.js +5 -0
  21. package/src/components/mediaPermission.js +21 -0
  22. package/src/components/onCanvas.js +2 -2
  23. package/src/components/sound.js +30 -2
  24. package/src/components/swalOptions.js +6 -3
  25. package/src/components/utils.js +27 -1
  26. package/src/components/video.js +9 -6
  27. package/src/const.js +15 -0
  28. package/src/core.js +103 -48
  29. package/src/css/buttons.scss +34 -7
  30. package/src/css/components.scss +57 -0
  31. package/src/css/distance.scss +71 -1
  32. package/src/css/gaze.css +9 -5
  33. package/src/css/main.css +22 -6
  34. package/src/css/panel.scss +33 -3
  35. package/src/css/screenSize.css +6 -5
  36. package/src/css/swal.css +1 -1
  37. package/src/css/video.scss +19 -0
  38. package/src/distance/distance.js +194 -41
  39. package/src/distance/distanceCheck.js +241 -0
  40. package/src/distance/distanceTrack.js +165 -68
  41. package/src/{interpupillaryDistance.js → distance/interPupillaryDistance.js} +27 -19
  42. package/src/gaze/gaze.js +4 -7
  43. package/src/gaze/gazeAccuracy.js +9 -4
  44. package/src/gaze/gazeCalibration.js +14 -4
  45. package/src/gaze/gazeTracker.js +40 -9
  46. package/src/i18n.js +1 -1
  47. package/src/index.js +7 -2
  48. package/src/media/two-side-arrow.svg +1 -0
  49. package/src/media/two-sided-horizontal.svg +1 -0
  50. package/src/media/two-sided-vertical.svg +3 -0
  51. package/src/panel.js +130 -65
  52. package/src/screenSize.js +38 -5
  53. package/webpack.config.js +7 -4
  54. package/media/measureDistance.png +0 -0
  55. package/media/panel.png +0 -0
  56. package/media/screenSize.png +0 -0
  57. package/media/trackGaze.png +0 -0
  58. package/src/displaySize.js +0 -28
@@ -6,9 +6,11 @@ import {
6
6
  constructInstructions,
7
7
  blurAll,
8
8
  sleep,
9
+ safeExecuteFunc,
9
10
  } from '../components/utils'
10
11
  import { iRepeat } from '../components/iRepeat'
11
12
  import { phrases } from '../i18n'
13
+ import { spaceForLanguage } from '../components/language'
12
14
 
13
15
  const originalStyles = {
14
16
  video: false,
@@ -41,17 +43,26 @@ RemoteCalibrator.prototype.trackDistance = function (
41
43
  {
42
44
  fullscreen: false,
43
45
  repeatTesting: 2,
44
- sparkle: true,
46
+ sparkle: false,
45
47
  pipWidthPx:
46
48
  this._CONST.N.VIDEO_W[this.isMobile.value ? 'MOBILE' : 'DESKTOP'],
47
49
  showVideo: true,
48
50
  showFaceOverlay: false,
49
51
  decimalPlace: 1,
50
- framerate: 3, // track rate
51
- nearPoint: true, // New 0.0.6
52
- showNearPoint: false, // New 0.0.6
53
- headline: '🙂 ' + phrases.RC_headTrackingTitle[this.L],
54
- description: phrases.RC_headTrackingIntro[this.L],
52
+ framerate: 3, // tracking rate
53
+ desiredDistanceCm: undefined,
54
+ desiredDistanceTolerance: 1.2,
55
+ desiredDistanceMonitor: false,
56
+ desiredDistanceMonitorCancelable: false,
57
+ nearPoint: true,
58
+ showNearPoint: false,
59
+ headline: '🙂 ' + phrases.RC_distanceTrackingTitle[this.L],
60
+ description:
61
+ phrases.RC_distanceTrackingIntroStart[this.L] +
62
+ spaceForLanguage(this.L) +
63
+ phrases.RC_viewingDistanceIntro[this.L] +
64
+ spaceForLanguage(this.L) +
65
+ phrases.RC_distanceTrackingIntroEnd[this.L],
55
66
  },
56
67
  options
57
68
  )
@@ -85,9 +96,7 @@ RemoteCalibrator.prototype.trackDistance = function (
85
96
  if (this.gazeTracker.checkInitialized('gaze', false))
86
97
  this.showGazer(originalGazer)
87
98
 
88
- if (callbackStatic && typeof callbackStatic === 'function')
89
- callbackStatic(distData)
90
-
99
+ safeExecuteFunc(callbackStatic, distData)
91
100
  stdDist.current = distData
92
101
  }
93
102
 
@@ -112,6 +121,12 @@ RemoteCalibrator.prototype.trackDistance = function (
112
121
  trackingOptions.nearPoint = options.nearPoint
113
122
  trackingOptions.showNearPoint = options.showNearPoint
114
123
 
124
+ trackingOptions.desiredDistanceCm = options.desiredDistanceCm
125
+ trackingOptions.desiredDistanceTolerance = options.desiredDistanceTolerance
126
+ trackingOptions.desiredDistanceMonitor = options.desiredDistanceMonitor
127
+ trackingOptions.desiredDistanceMonitorCancelable =
128
+ options.desiredDistanceMonitorCancelable
129
+
115
130
  originalStyles.video = options.showVideo
116
131
 
117
132
  this.gazeTracker._init(
@@ -123,41 +138,52 @@ RemoteCalibrator.prototype.trackDistance = function (
123
138
  'distance'
124
139
  )
125
140
 
141
+ this._trackingSetupFinishedStatus.distance = false
142
+
143
+ const trackingConfig = {
144
+ options: options,
145
+ callbackStatic: callbackStatic,
146
+ callbackTrack: callbackTrack,
147
+ }
148
+
126
149
  if (options.nearPoint) {
127
150
  startTrackingPupils(
128
151
  this,
129
152
  () => {
130
- this.measurePD({}, _)
153
+ this._measurePD({}, _)
131
154
  },
132
- callbackTrack
155
+ callbackTrack,
156
+ trackingConfig
133
157
  )
134
158
  } else {
135
- startTrackingPupils(this, _, callbackTrack)
159
+ startTrackingPupils(this, _, callbackTrack, trackingConfig)
136
160
  }
137
161
  }
138
162
 
139
163
  /* -------------------------------------------------------------------------- */
140
164
 
141
- const startTrackingPupils = async (RC, beforeCallbackTrack, callbackTrack) => {
165
+ const startTrackingPupils = async (
166
+ RC,
167
+ beforeCallbackTrack,
168
+ callbackTrack,
169
+ trackingConfig
170
+ ) => {
142
171
  RC.gazeTracker.beginVideo({ pipWidthPx: trackingOptions.pipWidthPx }, () => {
143
172
  RC._removeFloatInstructionElement()
144
- beforeCallbackTrack()
145
- _tracking(RC, trackingOptions, callbackTrack)
173
+ safeExecuteFunc(beforeCallbackTrack)
174
+ _tracking(RC, trackingOptions, callbackTrack, trackingConfig)
146
175
  })
147
176
  }
148
177
 
149
178
  const eyeDist = (a, b) => {
150
- return Math.sqrt(
151
- Math.pow(a[0] - b[0], 2) +
152
- Math.pow(a[1] - b[1], 2) +
153
- Math.pow(a[2] - b[2], 2)
154
- )
179
+ return Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2])
155
180
  }
156
181
 
157
182
  const cyclopean = (video, a, b) => {
158
- let [aX, aY] = [video.videoWidth - a[0], a[1]]
159
- let [bX, bY] = [video.videoWidth - b[0], b[1]]
160
- return [(aX + bX) / 2, (aY + bY) / 2]
183
+ return [
184
+ (-a[0] - b[0] + video.videoWidth) / 2,
185
+ (-a[1] - b[1] + video.videoHeight) / 2,
186
+ ]
161
187
  }
162
188
 
163
189
  /* -------------------------------------------------------------------------- */
@@ -167,6 +193,10 @@ const trackingOptions = {
167
193
  framerate: 3,
168
194
  nearPoint: true,
169
195
  showNearPoint: false,
196
+ desiredDistanceCm: undefined,
197
+ desiredDistanceTolerance: 1.2,
198
+ desiredDistanceMonitor: false,
199
+ desiredDistanceMonitorCancelable: false,
170
200
  }
171
201
 
172
202
  const stdDist = { current: null }
@@ -177,22 +207,31 @@ let iRepeatOptions = { framerate: 20, break: true }
177
207
  let nearPointDot = null
178
208
  /* -------------------------------------------------------------------------- */
179
209
 
180
- const _tracking = async (RC, trackingOptions, callbackTrack) => {
210
+ let readyToGetFirstData = false
211
+ let averageDist = 0
212
+ let distCount = 1
213
+
214
+ const _tracking = async (
215
+ RC,
216
+ trackingOptions,
217
+ callbackTrack,
218
+ trackingConfig
219
+ ) => {
181
220
  const video = document.querySelector('#webgazerVideoFeed')
182
221
 
183
222
  const _ = async () => {
184
223
  // const canvas = RC.gazeTracker.webgazer.videoCanvas
185
224
  let model, faces
186
225
 
187
- // Get the average of 2 estimates for one measure
188
- let averageDist = 0
189
- let distCount = 1
226
+ // Get the average of 5 estimates for one measure
227
+ averageDist = 0
228
+ distCount = 1
190
229
  const targetCount = 5
191
230
 
192
231
  model = await RC.gazeTracker.webgazer.getTracker().model
193
232
 
194
233
  // Near point
195
- let ppi = RC.screenPpi ? RC.screenPpi.value : 108
234
+ let ppi = RC.screenPpi ? RC.screenPpi.value : RC._CONST.N.PPI_DONT_USE
196
235
  if (!RC.screenPpi && trackingOptions.nearPoint)
197
236
  console.error(
198
237
  'Screen size measurement is required to get accurate near point tracking.'
@@ -215,29 +254,54 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
215
254
  })
216
255
  }
217
256
 
257
+ readyToGetFirstData = false
258
+ const {
259
+ desiredDistanceCm,
260
+ desiredDistanceTolerance,
261
+ desiredDistanceMonitor,
262
+ desiredDistanceMonitorCancelable,
263
+ } = trackingOptions
264
+
265
+ // Always enable correct on a fresh start
266
+ RC._distanceTrackNudging.distanceCorrectEnabled = true
267
+ RC._distanceTrackNudging.distanceDesired = desiredDistanceCm
268
+ RC._distanceTrackNudging.distanceAllowedRatio = desiredDistanceTolerance
269
+
218
270
  viewingDistanceTrackingFunction = async () => {
271
+ //
272
+ const videoTimestamp = new Date().getTime()
273
+ //
219
274
  faces = await model.estimateFaces(video)
220
275
  if (faces.length) {
221
276
  // There's at least one face in video
222
- const mesh = faces[0].scaledMesh
277
+ RC._tackingVideoFrameTimestamps.distance += videoTimestamp
223
278
  // https://github.com/tensorflow/tfjs-models/blob/master/facemesh/mesh_map.jpg
279
+ const mesh = faces[0].scaledMesh
280
+
224
281
  if (targetCount === distCount) {
225
282
  averageDist += eyeDist(mesh[133], mesh[362])
226
- averageDist /= 5
283
+ averageDist /= targetCount
284
+ RC._tackingVideoFrameTimestamps.distance /= targetCount
227
285
 
286
+ // TODO Add more samples for the first estimate
228
287
  if (stdDist.current !== null) {
229
288
  if (!stdFactor) {
230
289
  // ! First time estimate
231
290
  // Face_Known_Px * Distance_Known_Cm = Face_Now_Px * Distance_x_Cm
232
291
  // Get the factor to be used for future predictions
233
292
  stdFactor = averageDist * stdDist.current.value
234
- // FINISH
293
+ // ! FINISH
235
294
  RC._removeBackground()
295
+ RC._trackingSetupFinishedStatus.distance = true
296
+ readyToGetFirstData = true
236
297
  }
237
298
 
238
299
  /* -------------------------------------------------------------------------- */
239
300
 
240
301
  const timestamp = new Date()
302
+ const latency = Math.round(
303
+ timestamp.getTime() - RC._tackingVideoFrameTimestamps.distance
304
+ )
241
305
 
242
306
  const data = (RC.newViewingDistanceData = {
243
307
  value: toFixedNumber(
@@ -245,9 +309,20 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
245
309
  trackingOptions.decimalPlace
246
310
  ),
247
311
  timestamp: timestamp,
248
- method: 'Facemesh Predict',
312
+ method: RC._CONST.VIEW_METHOD.F,
313
+ latencyMs: latency,
249
314
  })
250
315
 
316
+ if (readyToGetFirstData || desiredDistanceMonitor) {
317
+ // ! Check distance
318
+ if (desiredDistanceCm)
319
+ RC.checkDistance(
320
+ desiredDistanceMonitorCancelable,
321
+ trackingConfig
322
+ )
323
+ readyToGetFirstData = false
324
+ }
325
+
251
326
  /* -------------------------------------------------------------------------- */
252
327
 
253
328
  // Near point
@@ -260,7 +335,8 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
260
335
  mesh,
261
336
  averageDist,
262
337
  timestamp,
263
- ppi
338
+ ppi,
339
+ latency
264
340
  )
265
341
  }
266
342
 
@@ -272,15 +348,18 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
272
348
  value: {
273
349
  viewingDistanceCm: data.value,
274
350
  nearPointCm: nPData ? nPData.value : [null, null],
351
+ latencyMs: latency,
275
352
  },
276
353
  timestamp: timestamp,
277
- method: 'Facemesh Predict',
354
+ method: RC._CONST.VIEW_METHOD.F,
278
355
  })
279
356
  }
280
357
  }
281
358
 
282
359
  averageDist = 0
283
360
  distCount = 1
361
+
362
+ RC._tackingVideoFrameTimestamps.distance = 0
284
363
  } else {
285
364
  averageDist += eyeDist(mesh[133], mesh[362])
286
365
  ++distCount
@@ -289,11 +368,11 @@ const _tracking = async (RC, trackingOptions, callbackTrack) => {
289
368
  }
290
369
 
291
370
  iRepeatOptions.break = false
292
- iRepeatOptions.framerate = targetCount * trackingOptions.framerate // Default 3 * 5
371
+ iRepeatOptions.framerate = targetCount * trackingOptions.framerate // Default 5 * 3
293
372
  iRepeat(viewingDistanceTrackingFunction, iRepeatOptions)
294
373
  }
295
374
 
296
- sleep(500).then(_)
375
+ sleep(1000).then(_)
297
376
  }
298
377
 
299
378
  const _getNearPoint = (
@@ -303,45 +382,42 @@ const _getNearPoint = (
303
382
  mesh,
304
383
  averageDist,
305
384
  timestamp,
306
- ppi
385
+ ppi,
386
+ latency
307
387
  ) => {
308
- let m = cyclopean(video, mesh[133], mesh[362])
309
- let offsetToVideoMid = [
310
- m[0] - video.videoWidth / 2,
311
- video.videoHeight / 2 - m[1],
312
- ]
313
-
314
- const videoFactor = video.videoHeight / video.clientHeight
315
- offsetToVideoMid.forEach((e, i) => {
316
- // Average interpupillary distance - 6.4cm
317
- offsetToVideoMid[i] =
318
- ((RC.PDCm ? RC.PDCm.value : 6.4) * e) /
319
- (averageDist * (videoFactor / 2)) /* Should this be videoFactor? */
388
+ let offsetToVideoCenter = cyclopean(video, mesh[133], mesh[362])
389
+ offsetToVideoCenter.forEach((offset, i) => {
390
+ // Average inter-pupillary distance - 6.4cm
391
+ offsetToVideoCenter[i] =
392
+ ((RC.PDCm ? RC.PDCm.value : RC._CONST.N.PD_DONT_USE) * offset) /
393
+ averageDist
320
394
  })
321
395
 
322
396
  let nPData = (RC.newNearPointData = {
323
397
  value: {
324
- x: toFixedNumber(offsetToVideoMid[0], trackingOptions.decimalPlace),
398
+ x: toFixedNumber(offsetToVideoCenter[0], trackingOptions.decimalPlace),
325
399
  y: toFixedNumber(
326
- offsetToVideoMid[1] + 0.5, // Commonly the webcam is 0.5cm above the screen
400
+ offsetToVideoCenter[1] + ((screen.height / 2) * 2.54) / ppi, // Commonly the webcam is 0.5cm above the screen
327
401
  trackingOptions.decimalPlace
328
402
  ),
403
+ latencyMs: latency,
329
404
  },
330
405
  timestamp: timestamp,
331
406
  })
332
407
 
333
408
  // SHOW
409
+ const dotR = 5
334
410
  if (trackingOptions.showNearPoint) {
335
411
  let offsetX = (nPData.value.x * ppi) / 2.54
336
412
  let offsetY = (nPData.value.y * ppi) / 2.54
337
413
  Object.assign(nearPointDot.style, {
338
- left: `${screen.width / 2 - window.screenLeft - 5 + offsetX}px`,
414
+ left: `${screen.width / 2 - window.screenLeft + offsetX - dotR}px`,
339
415
  top: `${
340
416
  screen.height / 2 -
341
417
  window.screenTop -
342
- 5 -
343
- (RC.isFullscreen.value ? 0 : 50) -
344
- offsetY
418
+ (window.outerHeight - window.innerHeight) -
419
+ offsetY -
420
+ dotR
345
421
  }px`,
346
422
  })
347
423
  }
@@ -353,6 +429,7 @@ RemoteCalibrator.prototype.pauseDistance = function () {
353
429
  if (this.gazeTracker.checkInitialized('distance', true)) {
354
430
  iRepeatOptions.break = true
355
431
  if (nearPointDot) nearPointDot.style.display = 'none'
432
+ this._tackingVideoFrameTimestamps.distance = 0
356
433
  return this
357
434
  }
358
435
  return null
@@ -362,6 +439,11 @@ RemoteCalibrator.prototype.resumeDistance = function () {
362
439
  if (this.gazeTracker.checkInitialized('distance', true)) {
363
440
  iRepeatOptions.break = false
364
441
  if (nearPointDot) nearPointDot.style.display = 'block'
442
+
443
+ averageDist = 0
444
+ distCount = 1
445
+ this._tackingVideoFrameTimestamps.distance = 0
446
+
365
447
  iRepeat(viewingDistanceTrackingFunction, iRepeatOptions)
366
448
  return this
367
449
  }
@@ -379,21 +461,30 @@ RemoteCalibrator.prototype.endDistance = function (endAll = false, _r = true) {
379
461
  trackingOptions.nearPoint = true
380
462
  trackingOptions.showNearPoint = false
381
463
 
464
+ trackingOptions.desiredDistanceCm = undefined
465
+ trackingOptions.desiredDistanceTolerance = 1.2
466
+ trackingOptions.desiredDistanceMonitor = false
467
+ trackingOptions.desiredDistanceMonitorCancelable = false
468
+
382
469
  stdDist.current = null
383
470
  stdFactor = null
384
471
  viewingDistanceTrackingFunction = null
385
472
 
473
+ readyToGetFirstData = false
474
+ this._tackingVideoFrameTimestamps.distance = 0
475
+
386
476
  // Near point
387
477
  if (nearPointDot) {
388
478
  document.body.removeChild(nearPointDot)
389
479
  nearPointDot = null
390
480
  }
391
481
 
392
- if (_r) this.gazeTracker.end('distance', endAll)
482
+ // Nudger
483
+ this.endNudger()
393
484
 
485
+ if (_r) this.gazeTracker.end('distance', endAll)
394
486
  return this
395
487
  }
396
-
397
488
  return null
398
489
  }
399
490
 
@@ -409,6 +500,7 @@ RemoteCalibrator.prototype.getDistanceNow = async function (callback = null) {
409
500
 
410
501
  let v = document.querySelector('#webgazerVideoFeed')
411
502
  let m = await this.gazeTracker.webgazer.getTracker().model
503
+ const videoTimestamp = new Date().getTime()
412
504
  let f = await m.estimateFaces(v)
413
505
 
414
506
  if (f.length) {
@@ -416,11 +508,15 @@ RemoteCalibrator.prototype.getDistanceNow = async function (callback = null) {
416
508
  const dist = eyeDist(mesh[133], mesh[362])
417
509
 
418
510
  let timestamp = new Date()
511
+ //
512
+ const latency = timestamp.getTime() - videoTimestamp
513
+ //
419
514
 
420
515
  const data = (this.newViewingDistanceData = {
421
516
  value: toFixedNumber(stdFactor / dist, trackingOptions.decimalPlace),
422
517
  timestamp: timestamp,
423
- method: 'Facemesh Predict',
518
+ method: this._CONST.VIEW_METHOD.F,
519
+ latencyMs: latency,
424
520
  })
425
521
 
426
522
  let nPData
@@ -432,19 +528,20 @@ RemoteCalibrator.prototype.getDistanceNow = async function (callback = null) {
432
528
  mesh,
433
529
  dist,
434
530
  timestamp,
435
- this.screenPpi ? this.screenPpi.value : 108
531
+ this.screenPpi ? this.screenPpi.value : this._CONST.N.PPI_DONT_USE,
532
+ latency
436
533
  )
437
534
  }
438
535
 
439
- if (c)
440
- c({
441
- value: {
442
- viewingDistanceCm: data.value,
443
- nearPointCm: nPData ? nPData.value : null,
444
- },
445
- timestamp: timestamp,
446
- method: 'Facemesh Predict',
447
- })
536
+ safeExecuteFunc(c, {
537
+ value: {
538
+ viewingDistanceCm: data.value,
539
+ nearPointCm: nPData ? nPData.value : null,
540
+ latencyMs: latency,
541
+ },
542
+ timestamp: timestamp,
543
+ method: this._CONST.VIEW_METHOD.F,
544
+ })
448
545
  return data
449
546
  }
450
547
 
@@ -1,19 +1,20 @@
1
1
  import Swal from 'sweetalert2'
2
2
 
3
- import RemoteCalibrator from './core'
3
+ import RemoteCalibrator from '../core'
4
4
 
5
5
  import {
6
6
  blurAll,
7
7
  constructInstructions,
8
+ safeExecuteFunc,
8
9
  toFixedNumber,
9
- } from './components/utils'
10
- import { swalInfoOptions } from './components/swalOptions'
11
- import Arrow from './media/arrow.svg'
12
- import PD from './media/pd.png?width=480&height=240'
13
- import { bindKeys, unbindKeys } from './components/keyBinder'
14
- import { addButtons } from './components/buttons'
15
- import { setDefaultVideoPosition } from './components/video'
16
- import { phrases } from './i18n'
10
+ } from '../components/utils'
11
+ import { swalInfoOptions } from '../components/swalOptions'
12
+ import Arrow from '../media/arrow.svg'
13
+ import PD from '../media/pd.png?width=480&height=240'
14
+ import { bindKeys, unbindKeys } from '../components/keyBinder'
15
+ import { addButtons } from '../components/buttons'
16
+ import { setDefaultVideoPosition } from '../components/video'
17
+ import { phrases } from '../i18n'
17
18
 
18
19
  // let selfVideo = false // No WebGazer video available and an extra video element needs to be created
19
20
 
@@ -29,7 +30,7 @@ const originalStyles = {
29
30
  const videoWidthFactor = 0.9
30
31
  const videoHeightFactor = 0.3
31
32
 
32
- RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
33
+ RemoteCalibrator.prototype._measurePD = function (options = {}, callback) {
33
34
  ////
34
35
  if (!this.checkInitialized()) return
35
36
  blurAll()
@@ -39,7 +40,7 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
39
40
  {
40
41
  fullscreen: false,
41
42
  headline: '👁️ ' + phrases.RC_nearPointTitle[this.L],
42
- description: phrases.RC_nearPointIntroCaption[this.L],
43
+ description: phrases.RC_nearPointIntro[this.L],
43
44
  shortDescription: phrases.RC_nearPointIntro[this.L],
44
45
  },
45
46
  options
@@ -50,9 +51,11 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
50
51
  this._replaceBackground()
51
52
 
52
53
  this._replaceBackground(
53
- constructInstructions(options.headline, options.shortDescription)
54
+ constructInstructions(options.headline, options.shortDescription, true)
54
55
  )
55
- const screenPpi = this.screenPpi ? this.screenPpi.value : 108
56
+ const screenPpi = this.screenPpi
57
+ ? this.screenPpi.value
58
+ : this._CONST.N.PPI_DONT_USE
56
59
 
57
60
  let [videoWidth, videoHeight] = setupVideo(this)
58
61
  let [ruler, rulerListener] = setupRuler(
@@ -64,7 +67,7 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
64
67
 
65
68
  const RC = this
66
69
 
67
- const breakFunction = () => {
70
+ const breakFunction = (toBreak = true) => {
68
71
  ruler.removeEventListener('mousedown', rulerListener)
69
72
  this._removeBackground()
70
73
 
@@ -77,7 +80,7 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
77
80
  height: originalStyles.videoHeight,
78
81
  width: originalStyles.videoWidth,
79
82
  opacity: originalStyles.opacity,
80
- borderRadius: '0px',
83
+ borderRadius: '5px',
81
84
  })
82
85
  setDefaultVideoPosition(
83
86
  RC,
@@ -99,6 +102,11 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
99
102
  originalStyles.gaze = false
100
103
  originalStyles.faceOverlay = false
101
104
 
105
+ if (!RC._trackingSetupFinishedStatus.distance && toBreak) {
106
+ RC._trackingSetupFinishedStatus.distance = true
107
+ RC.endDistance()
108
+ }
109
+
102
110
  unbindKeys(bindKeysFunction)
103
111
  }
104
112
 
@@ -110,14 +118,14 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
110
118
  }
111
119
  this.newPDData = newPDData
112
120
 
113
- breakFunction()
114
- callback()
121
+ breakFunction(false)
122
+ safeExecuteFunc(callback, newPDData)
115
123
  }
116
124
  }
117
125
 
118
- // if (callback && typeof callback === 'function') callback()
119
126
  const bindKeysFunction = bindKeys({
120
127
  Escape: breakFunction,
128
+ Enter: finishFunction,
121
129
  ' ': finishFunction,
122
130
  })
123
131
  addButtons(
@@ -133,7 +141,7 @@ RemoteCalibrator.prototype.measurePD = function (options = {}, callback) {
133
141
  // TODO To be removed
134
142
  setTimeout(() => {
135
143
  Swal.fire({
136
- ...swalInfoOptions(this),
144
+ ...swalInfoOptions(this, { showIcon: false }),
137
145
  icon: undefined,
138
146
  imageUrl: PD,
139
147
  imageWidth: 480,
package/src/gaze/gaze.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import RemoteCalibrator from '../core'
2
2
 
3
- import { blurAll } from '../components/utils'
3
+ import { blurAll, safeExecuteFunc } from '../components/utils'
4
4
  import { gazeCalibrationPrepare } from './gazeCalibration'
5
5
  import { phrases } from '../i18n'
6
6
 
@@ -97,17 +97,14 @@ RemoteCalibrator.prototype.trackGaze = function (
97
97
  description: options.description,
98
98
  }
99
99
  this.gazeTracker.begin(gazeTrackerBeginOptions, () => {
100
+ this._trackingSetupFinishedStatus.gaze = false
100
101
  this.calibrateGaze(calibrateGazeOptions, onCalibrationEnded)
101
102
  })
102
103
 
103
104
  // Calibration
104
105
 
105
- const onCalibrationEnded = () => {
106
- if (
107
- callbackOnCalibrationEnd &&
108
- typeof callbackOnCalibrationEnd === 'function'
109
- )
110
- callbackOnCalibrationEnd()
106
+ const onCalibrationEnded = data => {
107
+ safeExecuteFunc(callbackOnCalibrationEnd, data)
111
108
 
112
109
  // ! greedyLearner
113
110
  if (!this.gazeTracker.webgazer.params.greedyLearner) {
@@ -3,7 +3,12 @@ import Swal from 'sweetalert2/dist/sweetalert2.js'
3
3
  import RemoteCalibrator from '../core'
4
4
 
5
5
  import { _cross } from '../components/onCanvas'
6
- import { blurAll, sleep, toFixedNumber } from '../components/utils'
6
+ import {
7
+ blurAll,
8
+ safeExecuteFunc,
9
+ sleep,
10
+ toFixedNumber,
11
+ } from '../components/utils'
7
12
  import { swalInfoOptions } from '../components/swalOptions'
8
13
 
9
14
  let inGetAccuracy = false
@@ -57,7 +62,7 @@ RemoteCalibrator.prototype.getGazeAccuracy = function (
57
62
  _resizeCanvas()
58
63
 
59
64
  Swal.fire({
60
- ...swalInfoOptions(this),
65
+ ...swalInfoOptions(this, { showIcon: true }),
61
66
  // title: text.getGazeAccuracy.headline,
62
67
  html: `We will measure your gaze accuracy. Please do not move the mouse and look at the fixation at the middle of the screen for the next 5 seconds.`,
63
68
  }).then(() => {
@@ -88,8 +93,8 @@ RemoteCalibrator.prototype.getGazeAccuracy = function (
88
93
 
89
94
  if (averageDegree < options.thresholdDeg)
90
95
  // Success
91
- callbackSuccess()
92
- else callbackFail()
96
+ safeExecuteFunc(callbackSuccess)
97
+ else safeExecuteFunc(callbackFail)
93
98
 
94
99
  ctx.clearRect(0, 0, canvas.width, canvas.height)
95
100
  resizeObserver.unobserve(this.background)