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.
- package/CHANGELOG.md +35 -3
- package/README.md +34 -49
- package/homepage/example.css +4 -3
- package/homepage/example.js +42 -22
- package/homepage/index.html +19 -4
- package/i18n/fetch-languages-sheets.js +11 -1
- package/lib/RemoteCalibrator.min.js +1 -1
- package/lib/RemoteCalibrator.min.js.LICENSE.txt +19 -2
- package/lib/RemoteCalibrator.min.js.map +1 -1
- package/netlify.toml +1 -1
- package/package.json +25 -24
- package/src/WebGazer4RC/package-lock.json +198 -143
- package/src/WebGazer4RC/package.json +2 -2
- package/src/WebGazer4RC/src/index.mjs +161 -52
- package/src/WebGazer4RC/test/webgazer_test.js +1 -1
- package/src/check/checkScreenSize.js +84 -0
- package/src/components/buttons.js +21 -4
- package/src/components/input.js +82 -0
- package/src/components/keyBinder.js +5 -6
- package/src/components/language.js +5 -0
- package/src/components/mediaPermission.js +21 -0
- package/src/components/onCanvas.js +2 -2
- package/src/components/sound.js +30 -2
- package/src/components/swalOptions.js +6 -3
- package/src/components/utils.js +27 -1
- package/src/components/video.js +9 -6
- package/src/const.js +15 -0
- package/src/core.js +103 -48
- package/src/css/buttons.scss +34 -7
- package/src/css/components.scss +57 -0
- package/src/css/distance.scss +71 -1
- package/src/css/gaze.css +9 -5
- package/src/css/main.css +22 -6
- package/src/css/panel.scss +33 -3
- package/src/css/screenSize.css +6 -5
- package/src/css/swal.css +1 -1
- package/src/css/video.scss +19 -0
- package/src/distance/distance.js +194 -41
- package/src/distance/distanceCheck.js +241 -0
- package/src/distance/distanceTrack.js +165 -68
- package/src/{interpupillaryDistance.js → distance/interPupillaryDistance.js} +27 -19
- package/src/gaze/gaze.js +4 -7
- package/src/gaze/gazeAccuracy.js +9 -4
- package/src/gaze/gazeCalibration.js +14 -4
- package/src/gaze/gazeTracker.js +40 -9
- package/src/i18n.js +1 -1
- package/src/index.js +7 -2
- package/src/media/two-side-arrow.svg +1 -0
- package/src/media/two-sided-horizontal.svg +1 -0
- package/src/media/two-sided-vertical.svg +3 -0
- package/src/panel.js +130 -65
- package/src/screenSize.js +38 -5
- package/webpack.config.js +7 -4
- package/media/measureDistance.png +0 -0
- package/media/panel.png +0 -0
- package/media/screenSize.png +0 -0
- package/media/trackGaze.png +0 -0
- package/src/displaySize.js +0 -28
package/src/css/distance.scss
CHANGED
@@ -69,7 +69,7 @@
|
|
69
69
|
top: 0;
|
70
70
|
width: 2px;
|
71
71
|
transform: translate(-1px, 0);
|
72
|
-
z-index:
|
72
|
+
z-index: 2;
|
73
73
|
}
|
74
74
|
|
75
75
|
.rc-ruler-major {
|
@@ -87,3 +87,73 @@
|
|
87
87
|
height: 16px;
|
88
88
|
}
|
89
89
|
}
|
90
|
+
|
91
|
+
/* ---------------------------------- Check --------------------------------- */
|
92
|
+
|
93
|
+
.hide-nudger {
|
94
|
+
.calibration-nudger {
|
95
|
+
display: none !important;
|
96
|
+
opacity: 0 !important;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
.calibration-nudger {
|
101
|
+
z-index: 999999999;
|
102
|
+
position: fixed;
|
103
|
+
width: 100%;
|
104
|
+
height: 100%;
|
105
|
+
top: 0;
|
106
|
+
left: 0;
|
107
|
+
right: 0;
|
108
|
+
bottom: 0;
|
109
|
+
margin: 0;
|
110
|
+
overflow: hidden;
|
111
|
+
user-select: none;
|
112
|
+
box-sizing: border-box;
|
113
|
+
text-align: center;
|
114
|
+
scrollbar-width: none;
|
115
|
+
|
116
|
+
* {
|
117
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
118
|
+
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
#rc-distance-correct {
|
123
|
+
text-align: center;
|
124
|
+
width: 100%;
|
125
|
+
margin: 3rem auto auto auto;
|
126
|
+
padding: 2rem;
|
127
|
+
overflow-wrap: break-word;
|
128
|
+
|
129
|
+
#rc-distance-correct-instruction {
|
130
|
+
font-weight: 700;
|
131
|
+
font-size: 7rem;
|
132
|
+
margin: 2rem auto;
|
133
|
+
line-height: 100%;
|
134
|
+
}
|
135
|
+
|
136
|
+
#rc-distance-correct-guide {
|
137
|
+
font-weight: 500;
|
138
|
+
font-size: 3rem;
|
139
|
+
line-height: 150%;
|
140
|
+
|
141
|
+
.rc-distance-num {
|
142
|
+
padding: 0.5rem;
|
143
|
+
border-radius: 7px !important;
|
144
|
+
font-weight: 700;
|
145
|
+
font-family: monospace !important;
|
146
|
+
vertical-align: middle;
|
147
|
+
}
|
148
|
+
|
149
|
+
.rc-distance-now {
|
150
|
+
border: 2px solid #ff9a00;
|
151
|
+
background-color: #ff9a0066;
|
152
|
+
}
|
153
|
+
|
154
|
+
.rc-distance-desired {
|
155
|
+
border: 2px solid #3490de;
|
156
|
+
background-color: #3490de66;
|
157
|
+
}
|
158
|
+
}
|
159
|
+
}
|
package/src/css/gaze.css
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
position: fixed !important;
|
9
9
|
display: block;
|
10
10
|
cursor: initial;
|
11
|
-
z-index:
|
11
|
+
z-index: 999999998;
|
12
12
|
transition-timing-function: ease-in-out;
|
13
13
|
transition: left 0.5s, right 0.5s, top 0.5s, bottom 0.5s;
|
14
14
|
}
|
@@ -41,7 +41,7 @@
|
|
41
41
|
|
42
42
|
#webgazerGazeDot {
|
43
43
|
position: fixed;
|
44
|
-
z-index:
|
44
|
+
z-index: 9999999999;
|
45
45
|
opacity: 0.5;
|
46
46
|
background-color: #111d5e;
|
47
47
|
border-radius: 5px;
|
@@ -50,14 +50,18 @@
|
|
50
50
|
}
|
51
51
|
|
52
52
|
#webgazerVideoContainer {
|
53
|
-
z-index:
|
53
|
+
z-index: 999999997;
|
54
54
|
display: block;
|
55
55
|
position: fixed !important;
|
56
56
|
transform-origin: bottom left;
|
57
|
-
|
57
|
+
border-radius: 5px;
|
58
58
|
/* opacity: 0.8; */
|
59
59
|
overflow: hidden;
|
60
|
-
pointer-events: none;
|
60
|
+
/* pointer-events: none; */
|
61
|
+
user-select: none;
|
62
|
+
}
|
63
|
+
|
64
|
+
#webgazerVideoContainer * {
|
61
65
|
user-select: none;
|
62
66
|
}
|
63
67
|
|
package/src/css/main.css
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/* background div */
|
2
2
|
#calibration-background {
|
3
|
-
z-index:
|
3
|
+
z-index: 999999990;
|
4
4
|
position: fixed;
|
5
5
|
width: 100%;
|
6
6
|
height: 100%;
|
@@ -15,6 +15,12 @@
|
|
15
15
|
user-select: none;
|
16
16
|
box-sizing: border-box;
|
17
17
|
text-align: center;
|
18
|
+
scrollbar-width: none;
|
19
|
+
}
|
20
|
+
|
21
|
+
#calibration-background::-webkit-scrollbar {
|
22
|
+
width: 0;
|
23
|
+
display: none;
|
18
24
|
}
|
19
25
|
|
20
26
|
#calibration-background * {
|
@@ -28,7 +34,6 @@
|
|
28
34
|
|
29
35
|
.calibration-instruction {
|
30
36
|
position: absolute;
|
31
|
-
text-align: left;
|
32
37
|
user-select: none;
|
33
38
|
}
|
34
39
|
|
@@ -121,13 +126,13 @@
|
|
121
126
|
border-radius: 10px;
|
122
127
|
font-size: 1.2rem;
|
123
128
|
font-weight: 500;
|
124
|
-
z-index:
|
129
|
+
z-index: 999999991;
|
125
130
|
}
|
126
131
|
|
127
132
|
/* -------------------------------------------------------------------------- */
|
128
133
|
|
129
134
|
.swal2-container {
|
130
|
-
z-index:
|
135
|
+
z-index: 999999999 !important;
|
131
136
|
}
|
132
137
|
|
133
138
|
/* -------------------------------------------------------------------------- */
|
@@ -136,12 +141,11 @@
|
|
136
141
|
position: fixed !important;
|
137
142
|
width: 100% !important;
|
138
143
|
bottom: 3px !important;
|
139
|
-
left: 50% !important;
|
140
|
-
transform: translate(-50%, 0) !important;
|
141
144
|
color: #999 !important;
|
142
145
|
margin: 0 !important;
|
143
146
|
padding: 0 !important;
|
144
147
|
line-height: 100% !important;
|
148
|
+
text-align: center !important;
|
145
149
|
}
|
146
150
|
|
147
151
|
/* -------------------------------------------------------------------------- */
|
@@ -149,3 +153,15 @@
|
|
149
153
|
.lock-view {
|
150
154
|
overflow: hidden !important;
|
151
155
|
}
|
156
|
+
|
157
|
+
/* -------------------------------------------------------------------------- */
|
158
|
+
|
159
|
+
.rc-lang-ltr {
|
160
|
+
direction: ltr !important;
|
161
|
+
text-align: left !important;
|
162
|
+
}
|
163
|
+
|
164
|
+
.rc-lang-rtl {
|
165
|
+
direction: rtl !important;
|
166
|
+
text-align: right !important;
|
167
|
+
}
|
package/src/css/panel.scss
CHANGED
@@ -17,7 +17,6 @@
|
|
17
17
|
border-radius: 10px !important;
|
18
18
|
box-shadow: var(--rc-panel-darken-color-semi) 0px 50px 100px -20px,
|
19
19
|
var(--rc-panel-theme-color-semi) 0px 30px 60px -30px !important;
|
20
|
-
text-align: left !important;
|
21
20
|
|
22
21
|
* {
|
23
22
|
outline: none;
|
@@ -30,6 +29,7 @@
|
|
30
29
|
user-select: none;
|
31
30
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
32
31
|
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
32
|
+
scrollbar-width: none;
|
33
33
|
}
|
34
34
|
|
35
35
|
.rc-panel-title {
|
@@ -46,8 +46,27 @@
|
|
46
46
|
font-weight: 500 !important;
|
47
47
|
}
|
48
48
|
|
49
|
+
#rc-panel-language-parent {
|
50
|
+
display: flex;
|
51
|
+
flex-direction: row-reverse;
|
52
|
+
margin: 0;
|
53
|
+
padding: 0;
|
54
|
+
|
55
|
+
#rc-panel-lang-picker {
|
56
|
+
display: block;
|
57
|
+
background-color: #ffffffcc !important;
|
58
|
+
border: none !important;
|
59
|
+
outline: none !important;
|
60
|
+
margin: 0.25rem 0.25rem 0 0.25rem !important;
|
61
|
+
padding: 0.25rem !important;
|
62
|
+
font-size: 1rem !important;
|
63
|
+
font-weight: 500 !important;
|
64
|
+
border-radius: 5px !important;
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
49
68
|
.rc-panel-steps {
|
50
|
-
margin:
|
69
|
+
margin: 1rem 0 0 0 !important;
|
51
70
|
|
52
71
|
&.rc-panel-steps-l,
|
53
72
|
&.rc-panel-steps-s {
|
@@ -63,6 +82,10 @@
|
|
63
82
|
// overflow: hidden !important;
|
64
83
|
background: #ffffffcc;
|
65
84
|
|
85
|
+
// &:focus {
|
86
|
+
// outline: 3px solid black !important;
|
87
|
+
// }
|
88
|
+
|
66
89
|
.rc-panel-step-use {
|
67
90
|
position: absolute;
|
68
91
|
right: 0;
|
@@ -91,6 +114,8 @@
|
|
91
114
|
|
92
115
|
&.rc-panel-steps-l {
|
93
116
|
flex-flow: row nowrap;
|
117
|
+
max-width: 100%;
|
118
|
+
overflow-x: scroll;
|
94
119
|
|
95
120
|
.rc-panel-step-name {
|
96
121
|
margin: 1.5rem 0.5rem !important;
|
@@ -101,7 +126,7 @@
|
|
101
126
|
flex-flow: column nowrap;
|
102
127
|
|
103
128
|
.rc-panel-step {
|
104
|
-
|
129
|
+
overflow-x: hidden;
|
105
130
|
}
|
106
131
|
|
107
132
|
.rc-panel-step-name {
|
@@ -191,4 +216,9 @@
|
|
191
216
|
cursor: pointer;
|
192
217
|
}
|
193
218
|
}
|
219
|
+
|
220
|
+
::-webkit-scrollbar {
|
221
|
+
width: 0;
|
222
|
+
display: none;
|
223
|
+
}
|
194
224
|
}
|
package/src/css/screenSize.css
CHANGED
@@ -10,10 +10,11 @@
|
|
10
10
|
/* top: max(45%, 200px); */
|
11
11
|
left: 2rem;
|
12
12
|
border-radius: 5px;
|
13
|
-
z-index:
|
13
|
+
z-index: 10;
|
14
14
|
cursor: grab;
|
15
15
|
-webkit-transition: opacity 0.3s;
|
16
16
|
transition: opacity 0.3s;
|
17
|
+
direction: ltr !important;
|
17
18
|
}
|
18
19
|
|
19
20
|
.rc-slider:hover {
|
@@ -59,18 +60,18 @@
|
|
59
60
|
/* display: none; */
|
60
61
|
width: 70px;
|
61
62
|
height: auto;
|
62
|
-
z-index:
|
63
|
+
z-index: 1;
|
63
64
|
}
|
64
65
|
|
65
66
|
#size-arrow-fill {
|
66
|
-
transition: fill 0.
|
67
|
+
transition: fill 0.3s;
|
67
68
|
}
|
68
69
|
|
69
70
|
.minor {
|
70
|
-
transition: opacity 0.
|
71
|
+
transition: opacity 0.25s;
|
71
72
|
}
|
72
73
|
|
73
|
-
.rc-slider:hover ~ .size-obj .minor,
|
74
|
+
/* .rc-slider:hover ~ .size-obj .minor, */
|
74
75
|
.rc-slider:active ~ .size-obj .minor {
|
75
76
|
opacity: 0;
|
76
77
|
}
|
package/src/css/swal.css
CHANGED
@@ -20,12 +20,12 @@
|
|
20
20
|
}
|
21
21
|
|
22
22
|
.my__swal2__html {
|
23
|
+
margin: 1rem 1.6rem;
|
23
24
|
color: #444 !important;
|
24
25
|
font-size: 1.2rem !important;
|
25
26
|
line-height: 150% !important;
|
26
27
|
font-weight: normal !important;
|
27
28
|
user-select: none !important;
|
28
|
-
text-align: left !important;
|
29
29
|
}
|
30
30
|
|
31
31
|
.animate__animated.animate__fadeInUp,
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#webgazerVideoContainer {
|
2
|
+
.webgazer-videoinput-select {
|
3
|
+
z-index: 9;
|
4
|
+
position: absolute;
|
5
|
+
top: 0;
|
6
|
+
left: 0;
|
7
|
+
margin: 0.3rem;
|
8
|
+
padding: 0.2rem 0.3rem;
|
9
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
10
|
+
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
11
|
+
font-size: 0.6rem;
|
12
|
+
line-height: 100%;
|
13
|
+
border: none !important;
|
14
|
+
outline: none !important;
|
15
|
+
border-radius: 0.6rem !important;
|
16
|
+
background: #ffffffcc !important;
|
17
|
+
color: #666;
|
18
|
+
}
|
19
|
+
}
|
package/src/distance/distance.js
CHANGED
@@ -5,11 +5,13 @@ import {
|
|
5
5
|
toFixedNumber,
|
6
6
|
median,
|
7
7
|
blurAll,
|
8
|
+
safeExecuteFunc,
|
9
|
+
average,
|
8
10
|
} from '../components/utils'
|
9
11
|
import {
|
10
12
|
_getCrossX,
|
11
13
|
_cross,
|
12
|
-
circleDeltaX,
|
14
|
+
// circleDeltaX,
|
13
15
|
_getCircleBounds,
|
14
16
|
_circle,
|
15
17
|
} from '../components/onCanvas'
|
@@ -23,7 +25,7 @@ const blindSpotHTML = `<canvas id="blind-spot-canvas"></canvas>`
|
|
23
25
|
/* -------------------------------------------------------------------------- */
|
24
26
|
|
25
27
|
export function blindSpotTest(RC, options, toTrackDistance = false, callback) {
|
26
|
-
let ppi =
|
28
|
+
let ppi = RC._CONST.N.PPI_DONT_USE // Dangerous! Arbitrary value
|
27
29
|
if (RC.screenPpi) ppi = RC.screenPpi.value
|
28
30
|
else
|
29
31
|
console.error(
|
@@ -40,7 +42,7 @@ export function blindSpotTest(RC, options, toTrackDistance = false, callback) {
|
|
40
42
|
RC.background.appendChild(blindSpotDiv)
|
41
43
|
RC._constructFloatInstructionElement(
|
42
44
|
'blind-spot-instruction',
|
43
|
-
phrases.
|
45
|
+
phrases.RC_distanceTrackingCloseL[RC.L]
|
44
46
|
)
|
45
47
|
RC._addCreditOnBackground(phrases.RC_viewingBlindSpotCredit[RC.L])
|
46
48
|
|
@@ -74,63 +76,186 @@ export function blindSpotTest(RC, options, toTrackDistance = false, callback) {
|
|
74
76
|
let v = eyeSide === 'left' ? 1 : -1
|
75
77
|
|
76
78
|
// ! KEY
|
77
|
-
const breakFunction = () => {
|
79
|
+
const breakFunction = (toBreakTracking = true) => {
|
78
80
|
// ! BREAK
|
79
81
|
inTest = false
|
80
82
|
resizeObserver.unobserve(RC.background)
|
81
83
|
RC._removeBackground()
|
82
84
|
|
85
|
+
if (!RC._trackingSetupFinishedStatus.distance && toBreakTracking) {
|
86
|
+
RC._trackingSetupFinishedStatus.distance = true
|
87
|
+
if (RC.gazeTracker.checkInitialized('distance', false)) RC.endDistance()
|
88
|
+
}
|
89
|
+
|
83
90
|
unbindKeys(bindKeysFunction)
|
91
|
+
unbindKeys(bindKeyUpsFunction, 'keyup')
|
84
92
|
}
|
85
93
|
|
86
94
|
// SPACE
|
87
95
|
const finishFunction = () => {
|
96
|
+
customButton.disabled = false
|
88
97
|
soundFeedback()
|
89
98
|
|
90
99
|
tested += 1
|
91
100
|
// Average
|
92
|
-
dist.push(
|
93
|
-
toFixedNumber(_getDist(circleX, crossX, ppi), options.decimalPlace)
|
94
|
-
|
101
|
+
dist.push({
|
102
|
+
dist: toFixedNumber(_getDist(circleX, crossX, ppi), options.decimalPlace),
|
103
|
+
v: v,
|
104
|
+
closedEyeSide: eyeSide,
|
105
|
+
crossX: crossX,
|
106
|
+
circleX: circleX,
|
107
|
+
ppi: ppi,
|
108
|
+
timestamp: new Date(),
|
109
|
+
})
|
95
110
|
|
96
111
|
// Enough tests?
|
97
112
|
if (Math.floor(tested / options.repeatTesting) === 2) {
|
98
|
-
//
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
113
|
+
// Check if these data are acceptable
|
114
|
+
if (checkDataRepeatability(dist)) {
|
115
|
+
// ! Put dist into data and callback function
|
116
|
+
const data = (RC.newViewingDistanceData = {
|
117
|
+
value: toFixedNumber(
|
118
|
+
median(_getDistValues(dist)),
|
119
|
+
options.decimalPlace
|
120
|
+
),
|
121
|
+
timestamp: new Date(),
|
122
|
+
method: RC._CONST.VIEW_METHOD.B,
|
123
|
+
raw: { ...dist },
|
124
|
+
})
|
125
|
+
safeExecuteFunc(callback, data)
|
126
|
+
|
127
|
+
// Break
|
128
|
+
if (!toTrackDistance) {
|
129
|
+
breakFunction(false)
|
130
|
+
} else {
|
131
|
+
// ! For tracking
|
132
|
+
// Stop test
|
133
|
+
inTest = false
|
134
|
+
// Clear observer and keys
|
135
|
+
resizeObserver.unobserve(RC.background)
|
136
|
+
unbindKeys(bindKeysFunction)
|
137
|
+
unbindKeys(bindKeyUpsFunction, 'keyup')
|
138
|
+
}
|
109
139
|
} else {
|
110
|
-
// !
|
111
|
-
|
112
|
-
|
113
|
-
//
|
114
|
-
|
115
|
-
|
140
|
+
// ! Reset
|
141
|
+
tested = 0
|
142
|
+
customButton.disabled = true
|
143
|
+
// Get first response
|
144
|
+
const firstResponse = dist[0]
|
145
|
+
_resetCanvasLayout(
|
146
|
+
firstResponse.v,
|
147
|
+
firstResponse.closedEyeSide,
|
148
|
+
firstResponse.crossX
|
149
|
+
)
|
116
150
|
}
|
117
151
|
} else if (tested % options.repeatTesting === 0) {
|
118
152
|
// Switch eye side
|
119
153
|
if (eyeSide === 'left') {
|
120
154
|
// Change to RIGHT
|
121
155
|
eyeSide = 'right'
|
122
|
-
eyeSideEle.innerHTML = phrases.
|
156
|
+
eyeSideEle.innerHTML = phrases.RC_distanceTrackingCloseR[RC.L]
|
123
157
|
} else {
|
124
158
|
eyeSide = 'left'
|
125
|
-
eyeSideEle.innerHTML = phrases.
|
159
|
+
eyeSideEle.innerHTML = phrases.RC_distanceTrackingCloseL[RC.L]
|
160
|
+
}
|
161
|
+
RC._setFloatInstructionElementPos(eyeSide, 16)
|
162
|
+
|
163
|
+
_resetCanvasLayout(
|
164
|
+
// eyeSide === 'left' ? 1 : -1, // v
|
165
|
+
1, // v
|
166
|
+
eyeSide, // eyeSide
|
167
|
+
_getCrossX(eyeSide, c.width), // crossX
|
168
|
+
false,
|
169
|
+
true
|
170
|
+
)
|
171
|
+
} else {
|
172
|
+
// Shift circle
|
173
|
+
v = -v
|
174
|
+
if (v > 0)
|
175
|
+
// Going to the right
|
176
|
+
circleX = circleBounds[0]
|
177
|
+
else if (v < 0) circleX = circleBounds[1]
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
const redoFunction = () => {
|
182
|
+
if (!tested) return
|
183
|
+
tested--
|
184
|
+
customButton.disabled = true
|
185
|
+
|
186
|
+
soundFeedback(3)
|
187
|
+
|
188
|
+
const lastResponse = dist.pop()
|
189
|
+
_resetCanvasLayout(
|
190
|
+
lastResponse.v,
|
191
|
+
lastResponse.closedEyeSide,
|
192
|
+
lastResponse.crossX,
|
193
|
+
true,
|
194
|
+
true
|
195
|
+
)
|
196
|
+
}
|
197
|
+
|
198
|
+
let arrowKeyDown = false
|
199
|
+
let arrowIntervalFunction = null
|
200
|
+
const arrowDownFunction = e => {
|
201
|
+
if (arrowKeyDown) return
|
202
|
+
|
203
|
+
arrowUpFunction()
|
204
|
+
arrowKeyDown = true
|
205
|
+
|
206
|
+
arrowIntervalFunction = setInterval(() => {
|
207
|
+
if (e.key === 'ArrowLeft') {
|
208
|
+
circleX -= 10
|
209
|
+
helpMoveCircleX()
|
210
|
+
} else if (e.key === 'ArrowRight') {
|
211
|
+
circleX += 10
|
212
|
+
helpMoveCircleX()
|
126
213
|
}
|
214
|
+
}, 30)
|
215
|
+
}
|
216
|
+
|
217
|
+
const arrowUpFunction = () => {
|
218
|
+
arrowKeyDown = false
|
219
|
+
if (arrowIntervalFunction) {
|
220
|
+
clearInterval(arrowIntervalFunction)
|
221
|
+
arrowIntervalFunction = null
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
const helpMoveCircleX = () => {
|
226
|
+
tempX = constrain(circleX, ...circleBounds)
|
227
|
+
if (circleX !== tempX) {
|
228
|
+
circleX = tempX
|
229
|
+
for (let b of circleBounds)
|
230
|
+
if (circleX !== b) {
|
231
|
+
circleX = b
|
232
|
+
break
|
233
|
+
}
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
const _resetCanvasLayout = (
|
238
|
+
nextV,
|
239
|
+
nextEyeSide,
|
240
|
+
nextCrossX,
|
241
|
+
shiftFloatingElement = true,
|
242
|
+
shiftCircle = true
|
243
|
+
) => {
|
244
|
+
v = nextV
|
245
|
+
eyeSide = nextEyeSide
|
246
|
+
crossX = nextCrossX
|
247
|
+
circleBounds = _getCircleBounds(eyeSide, crossX, c.width)
|
248
|
+
|
249
|
+
if (shiftFloatingElement) {
|
250
|
+
if (eyeSide === 'left')
|
251
|
+
eyeSideEle.innerHTML = phrases.RC_distanceTrackingCloseL[RC.L]
|
252
|
+
else eyeSideEle.innerHTML = phrases.RC_distanceTrackingCloseR[RC.L]
|
127
253
|
RC._setFloatInstructionElementPos(eyeSide, 16)
|
254
|
+
}
|
128
255
|
|
129
|
-
|
130
|
-
circleX = circleBounds[
|
131
|
-
|
132
|
-
crossX = _getCrossX(eyeSide, c.width)
|
133
|
-
circleBounds = _getCircleBounds(eyeSide, crossX, c.width)
|
256
|
+
if (shiftCircle) {
|
257
|
+
if (v > 0) circleX = circleBounds[0]
|
258
|
+
else circleX = circleBounds[1]
|
134
259
|
}
|
135
260
|
}
|
136
261
|
|
@@ -138,17 +263,33 @@ export function blindSpotTest(RC, options, toTrackDistance = false, callback) {
|
|
138
263
|
const bindKeysFunction = bindKeys({
|
139
264
|
Escape: breakFunction,
|
140
265
|
' ': finishFunction,
|
266
|
+
ArrowLeft: arrowDownFunction,
|
267
|
+
ArrowRight: arrowDownFunction,
|
141
268
|
})
|
142
|
-
|
269
|
+
const bindKeyUpsFunction = bindKeys(
|
270
|
+
{
|
271
|
+
ArrowLeft: arrowUpFunction,
|
272
|
+
ArrowRight: arrowUpFunction,
|
273
|
+
},
|
274
|
+
'keyup'
|
275
|
+
)
|
276
|
+
const addedButtons = addButtons(
|
143
277
|
RC.L,
|
144
278
|
RC.background,
|
145
279
|
{
|
146
280
|
go: finishFunction,
|
147
281
|
cancel: breakFunction,
|
282
|
+
custom: {
|
283
|
+
callback: redoFunction,
|
284
|
+
content: phrases.RC_viewingDistanceRedo[RC.L],
|
285
|
+
},
|
148
286
|
},
|
149
287
|
RC.params.showCancelButton
|
150
288
|
)
|
151
289
|
|
290
|
+
const customButton = addedButtons[3]
|
291
|
+
customButton.disabled = true
|
292
|
+
|
152
293
|
// ! ACTUAL TEST
|
153
294
|
let frameCount = 0
|
154
295
|
const runTest = () => {
|
@@ -160,12 +301,7 @@ export function blindSpotTest(RC, options, toTrackDistance = false, callback) {
|
|
160
301
|
_cross(ctx, crossX, c.height / 2)
|
161
302
|
|
162
303
|
_circle(RC, ctx, circleX, c.height / 2, frameCount, options.sparkle)
|
163
|
-
circleX += v * circleDeltaX
|
164
|
-
tempX = constrain(circleX, ...circleBounds)
|
165
|
-
if (circleX !== tempX) {
|
166
|
-
circleX = tempX
|
167
|
-
v = -v
|
168
|
-
}
|
304
|
+
// circleX += v * circleDeltaX
|
169
305
|
|
170
306
|
if (inTest) {
|
171
307
|
frameCount++
|
@@ -183,7 +319,6 @@ RemoteCalibrator.prototype.measureDistance = function (options = {}, callback) {
|
|
183
319
|
* options -
|
184
320
|
*
|
185
321
|
* fullscreen: [Boolean]
|
186
|
-
* quitFullscreenOnFinished: [Boolean] // TODO
|
187
322
|
* repeatTesting: 2
|
188
323
|
* sparkle: true
|
189
324
|
* decimalPlace: 1
|
@@ -200,9 +335,8 @@ RemoteCalibrator.prototype.measureDistance = function (options = {}, callback) {
|
|
200
335
|
options = Object.assign(
|
201
336
|
{
|
202
337
|
fullscreen: false,
|
203
|
-
quitFullscreenOnFinished: false,
|
204
338
|
repeatTesting: 2,
|
205
|
-
sparkle:
|
339
|
+
sparkle: false,
|
206
340
|
decimalPlace: 1,
|
207
341
|
headline: '📏 ' + phrases.RC_viewingDistanceTitle[this.L],
|
208
342
|
description: phrases.RC_viewingDistanceIntro[this.L],
|
@@ -230,3 +364,22 @@ function _getDist(x, crossX, ppi) {
|
|
230
364
|
function _getTanDeg(deg) {
|
231
365
|
return Math.tan((deg * Math.PI) / 180)
|
232
366
|
}
|
367
|
+
|
368
|
+
function checkDataRepeatability(dist) {
|
369
|
+
let lefts = []
|
370
|
+
let rights = []
|
371
|
+
for (let d of dist) {
|
372
|
+
if (d.closedEyeSide === 'left') lefts.push(d.dist)
|
373
|
+
else rights.push(d.dist)
|
374
|
+
}
|
375
|
+
const leftMean = average(lefts)
|
376
|
+
const rightMean = average(rights)
|
377
|
+
|
378
|
+
return Math.abs(leftMean - rightMean) < 0.2 * Math.min(leftMean, rightMean)
|
379
|
+
}
|
380
|
+
|
381
|
+
function _getDistValues(dist) {
|
382
|
+
const v = []
|
383
|
+
for (let d of dist) v.push(d.dist)
|
384
|
+
return v
|
385
|
+
}
|