tracky-mouse 1.1.0 → 1.2.0
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/README.md +19 -5
- package/package.json +1 -1
- package/tracky-mouse.js +65 -11
package/README.md
CHANGED
|
@@ -102,13 +102,16 @@ TrackyMouse.loadDependencies().then(function() {
|
|
|
102
102
|
|
|
103
103
|
Set this to the path to the folder where you installed tracky-mouse, without a trailing slash.
|
|
104
104
|
|
|
105
|
-
### `TrackyMouse.loadDependencies()`
|
|
105
|
+
### `TrackyMouse.loadDependencies([options])`
|
|
106
106
|
|
|
107
107
|
This loads dependencies needed *for head tracking*. (It is not needed for dwell clicking.)
|
|
108
108
|
|
|
109
|
+
If you pass an options object, it can have the following properties:
|
|
110
|
+
- `statsJs` (optional): a boolean, whether to load stats.js for performance monitoring. Default is `false`.
|
|
111
|
+
|
|
109
112
|
Returns a promise that resolves when the dependencies are loaded.
|
|
110
113
|
|
|
111
|
-
### `TrackyMouse.init([element])`
|
|
114
|
+
### `TrackyMouse.init([element, options])`
|
|
112
115
|
|
|
113
116
|
`TrackyMouse.init` initializes the library *for head tracking*. (It is not needed for dwell clicking.)
|
|
114
117
|
|
|
@@ -118,6 +121,13 @@ or using, and modifying, and existing element.
|
|
|
118
121
|
If you pass an element, it should be an empty `<div>` element.
|
|
119
122
|
It will add `class="tracky-mouse-ui"` directly to the element if it doesn't already have it.
|
|
120
123
|
|
|
124
|
+
If you pass an options object, it can have the following properties:
|
|
125
|
+
- `statsJs` (optional): a boolean, whether to include the stats.js performance monitor. Default is `false`.
|
|
126
|
+
|
|
127
|
+
Returns an object with a `dispose` method that you can call to remove the UI and clean up the web worker and camera stream.
|
|
128
|
+
|
|
129
|
+
*(Search keywords: disposal, destroy, teardown, cleanup, clean-up, clean up, deinitialize, de-initialize, remove, stop, end)* - see return value
|
|
130
|
+
|
|
121
131
|
### `TrackyMouse.useCamera()`
|
|
122
132
|
|
|
123
133
|
This requests permission to use the camera, and starts the camera stream.
|
|
@@ -154,8 +164,8 @@ Arguments:
|
|
|
154
164
|
|
|
155
165
|
Returns an object with the following properties:
|
|
156
166
|
- `paused`: a getter/setter for whether dwell clicking is paused. Use this to implement a pause/resume button, in conjunction with `config.dwellClickEvenIfPaused`.
|
|
157
|
-
-
|
|
158
|
-
|
|
167
|
+
- `dispose`: a method to clean up the dwell clicker.
|
|
168
|
+
*(Search keywords: disposal, destroy, teardown, cleanup, clean-up, clean up, deinitialize, de-initialize, remove, stop, end)*
|
|
159
169
|
|
|
160
170
|
Example:
|
|
161
171
|
```javascript
|
|
@@ -248,7 +258,9 @@ const config = {
|
|
|
248
258
|
beforePointerDownDispatch: () => { window.pointers = []; },
|
|
249
259
|
afterReleaseDrag: () => { window.pointers = []; },
|
|
250
260
|
};
|
|
251
|
-
TrackyMouse.initDwellClicking(config);
|
|
261
|
+
const dwellClicker = TrackyMouse.initDwellClicking(config);
|
|
262
|
+
// dwellClicker.paused = !dwellClicker.paused; // toggle
|
|
263
|
+
// dwellClicker.dispose(); // clean up
|
|
252
264
|
|
|
253
265
|
// Source: https://stackoverflow.com/a/54492696/2624876
|
|
254
266
|
function getCurrentRotation(el) {
|
|
@@ -269,6 +281,8 @@ function getCurrentRotation(el) {
|
|
|
269
281
|
|
|
270
282
|
### `TrackyMouse.cleanupDwellClicking()`
|
|
271
283
|
|
|
284
|
+
**Deprecated**: instead call `dispose()` on the object returned from `initDwellClicking()`.
|
|
285
|
+
|
|
272
286
|
This stops the dwell clicker.
|
|
273
287
|
|
|
274
288
|
## Changelog
|
package/package.json
CHANGED
package/tracky-mouse.js
CHANGED
|
@@ -3,7 +3,7 @@ const TrackyMouse = {
|
|
|
3
3
|
dependenciesRoot: "./tracky-mouse",
|
|
4
4
|
};
|
|
5
5
|
|
|
6
|
-
TrackyMouse.loadDependencies = function () {
|
|
6
|
+
TrackyMouse.loadDependencies = function ({ statsJs = false } = {}) {
|
|
7
7
|
TrackyMouse.dependenciesRoot = TrackyMouse.dependenciesRoot.replace(/\/+$/, "");
|
|
8
8
|
const loadScript = src => {
|
|
9
9
|
return new Promise((resolve, reject) => {
|
|
@@ -25,8 +25,10 @@ TrackyMouse.loadDependencies = function () {
|
|
|
25
25
|
const scriptFiles = [
|
|
26
26
|
`${TrackyMouse.dependenciesRoot}/lib/no-eval.js`, // generated with eval-is-evil.html, this instruments clmtrackr.js so I don't need unsafe-eval in the CSP
|
|
27
27
|
`${TrackyMouse.dependenciesRoot}/lib/clmtrackr.js`,
|
|
28
|
-
`${TrackyMouse.dependenciesRoot}/lib/stats.js`,
|
|
29
28
|
];
|
|
29
|
+
if (statsJs) {
|
|
30
|
+
scriptFiles.push(`${TrackyMouse.dependenciesRoot}/lib/stats.js`);
|
|
31
|
+
}
|
|
30
32
|
// TODO: figure out how to preload worker-context dependencies that use `importScripts`.
|
|
31
33
|
// `<link rel="preload">` can be injected at runtime,
|
|
32
34
|
// which wouldn't make sense for the main thread's dependencies, since we're injecting all the scripts at once anyway,
|
|
@@ -46,7 +48,9 @@ const is_selector_valid = ((dummy_element) =>
|
|
|
46
48
|
return true;
|
|
47
49
|
})(document.createDocumentFragment());
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
|
|
52
|
+
const dwell_clickers = [];
|
|
53
|
+
|
|
50
54
|
const init_dwell_clicking = (config) => {
|
|
51
55
|
/*
|
|
52
56
|
Arguments:
|
|
@@ -525,7 +529,7 @@ const init_dwell_clicking = (config) => {
|
|
|
525
529
|
};
|
|
526
530
|
raf_id = requestAnimationFrame(animate);
|
|
527
531
|
|
|
528
|
-
|
|
532
|
+
const dispose = () => {
|
|
529
533
|
cancelAnimationFrame(raf_id);
|
|
530
534
|
halo.remove();
|
|
531
535
|
dwell_indicator.remove();
|
|
@@ -536,7 +540,6 @@ const init_dwell_clicking = (config) => {
|
|
|
536
540
|
window.removeEventListener("blur", on_blur);
|
|
537
541
|
document.removeEventListener("mouseleave", on_mouse_leave_page);
|
|
538
542
|
document.removeEventListener("mouseenter", on_mouse_enter_page);
|
|
539
|
-
clean_up_dwell_clicking = () => { };
|
|
540
543
|
};
|
|
541
544
|
|
|
542
545
|
const dwellClicker = {
|
|
@@ -545,8 +548,10 @@ const init_dwell_clicking = (config) => {
|
|
|
545
548
|
},
|
|
546
549
|
set paused(value) {
|
|
547
550
|
paused = value;
|
|
548
|
-
}
|
|
551
|
+
},
|
|
552
|
+
dispose,
|
|
549
553
|
};
|
|
554
|
+
dwell_clickers.push(dwellClicker);
|
|
550
555
|
return dwellClicker;
|
|
551
556
|
};
|
|
552
557
|
|
|
@@ -554,10 +559,12 @@ TrackyMouse.initDwellClicking = function (config) {
|
|
|
554
559
|
return init_dwell_clicking(config);
|
|
555
560
|
};
|
|
556
561
|
TrackyMouse.cleanupDwellClicking = function () {
|
|
557
|
-
|
|
562
|
+
for (const dwell_clicker of dwell_clickers) {
|
|
563
|
+
dwell_clicker.dispose();
|
|
564
|
+
}
|
|
558
565
|
};
|
|
559
566
|
|
|
560
|
-
TrackyMouse.init = function (div) {
|
|
567
|
+
TrackyMouse.init = function (div, { statsJs = false } = {}) {
|
|
561
568
|
|
|
562
569
|
var uiContainer = div || document.createElement("div");
|
|
563
570
|
uiContainer.classList.add("tracky-mouse-ui");
|
|
@@ -706,7 +713,7 @@ TrackyMouse.init = function (div) {
|
|
|
706
713
|
// required to work in iOS 11 & up:
|
|
707
714
|
cameraVideo.setAttribute('playsinline', '');
|
|
708
715
|
|
|
709
|
-
if (
|
|
716
|
+
if (statsJs) {
|
|
710
717
|
var stats = new Stats();
|
|
711
718
|
stats.domElement.style.position = 'absolute';
|
|
712
719
|
stats.domElement.style.top = '0px';
|
|
@@ -1834,13 +1841,60 @@ TrackyMouse.init = function (div) {
|
|
|
1834
1841
|
if (window.electronAPI) {
|
|
1835
1842
|
window.electronAPI.onShortcut(handleShortcut);
|
|
1836
1843
|
}
|
|
1837
|
-
|
|
1844
|
+
const handleKeydown = (event) => {
|
|
1838
1845
|
// Same shortcut as the global shortcut in the electron app
|
|
1839
1846
|
if (!event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey && event.key === "F9") {
|
|
1840
1847
|
handleShortcut("toggle-tracking");
|
|
1841
1848
|
}
|
|
1842
|
-
}
|
|
1849
|
+
};
|
|
1850
|
+
addEventListener("keydown", handleKeydown);
|
|
1851
|
+
|
|
1852
|
+
return {
|
|
1853
|
+
dispose() {
|
|
1854
|
+
// TODO: re-structure so that cleanup can succeed even if initialization fails
|
|
1855
|
+
// OOP would help with this, by storing references in an object, but it doesn't necessarily
|
|
1856
|
+
// need to be converted to a class, it could just be an object, with a try-finally used for returning the API with a `dispose` method.
|
|
1857
|
+
// Wouldn't need to change the API that way.
|
|
1858
|
+
// (Would also be easy to maintain backwards compatibility while switching to using a class,
|
|
1859
|
+
// returning an instance of the class from `TrackyMouse.init` but deprecating it in favor of constructing the class.)
|
|
1860
|
+
|
|
1861
|
+
// clean up camera stream
|
|
1862
|
+
if (cameraVideo.srcObject) {
|
|
1863
|
+
for (const track of cameraVideo.srcObject.getTracks()) {
|
|
1864
|
+
track.stop();
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
cameraVideo.srcObject = null; // probably pointless
|
|
1843
1868
|
|
|
1869
|
+
// not sure this helps
|
|
1870
|
+
reset();
|
|
1871
|
+
// just in case there's any async code looking at whether it's paused
|
|
1872
|
+
paused = true;
|
|
1873
|
+
|
|
1874
|
+
if (facemeshWorker) {
|
|
1875
|
+
facemeshWorker.terminate();
|
|
1876
|
+
}
|
|
1877
|
+
if (clmTracker) {
|
|
1878
|
+
// not sure this helps clean up any resources
|
|
1879
|
+
clmTracker.reset();
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
pointerEl.remove();
|
|
1883
|
+
|
|
1884
|
+
stats?.domElement.remove(); // there is no dispose method but this may be all that it would need to do https://github.com/mrdoob/stats.js/pull/96
|
|
1885
|
+
|
|
1886
|
+
removeEventListener("keydown", handleKeydown);
|
|
1887
|
+
|
|
1888
|
+
// This is a little awkward, reversing the initialization based on a possibly-preexisting element
|
|
1889
|
+
// Could save and restore innerHTML but that won't restore event listeners, references, etc.
|
|
1890
|
+
// and may not even be desired if the HTML was placeholder text mentioning it not yet being initialized for example.
|
|
1891
|
+
uiContainer.classList.remove("tracky-mouse-ui");
|
|
1892
|
+
uiContainer.innerHTML = "";
|
|
1893
|
+
if (!div) {
|
|
1894
|
+
uiContainer.remove();
|
|
1895
|
+
}
|
|
1896
|
+
},
|
|
1897
|
+
};
|
|
1844
1898
|
};
|
|
1845
1899
|
|
|
1846
1900
|
// CommonJS export is untested. Script tag usage recommended.
|