remote-calibrator 0.3.0-rc.3 → 0.5.0-beta.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|