mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-10 19:20:55 +00:00
initial commit of mouse tracking plugin
This commit is contained in:
parent
6aad6315df
commit
6aa4e5c441
1
packages/extension-mouse-tracking/jest.config.cjs
Normal file
1
packages/extension-mouse-tracking/jest.config.cjs
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require("@jspsych/config/jest").makePackageConfig(__dirname);
|
43
packages/extension-mouse-tracking/package.json
Normal file
43
packages/extension-mouse-tracking/package.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "@jspsych/extension-mouse-tracking",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "jsPsych extension for mouse tracking",
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.cjs",
|
||||||
|
"exports": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.cjs"
|
||||||
|
},
|
||||||
|
"typings": "dist/index.d.ts",
|
||||||
|
"unpkg": "dist/index.browser.min.js",
|
||||||
|
"files": [
|
||||||
|
"src",
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"source": "src/index.ts",
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest --passWithNoTests",
|
||||||
|
"test:watch": "npm test -- --watch",
|
||||||
|
"tsc": "tsc",
|
||||||
|
"build": "rollup --config",
|
||||||
|
"build:watch": "npm run build -- --watch"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/jspsych/jsPsych.git",
|
||||||
|
"directory": "packages/extension-webgazer"
|
||||||
|
},
|
||||||
|
"author": "Josh de Leeuw",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/jspsych/jsPsych/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://www.jspsych.org/latest/extensions/mouse-tracking",
|
||||||
|
"peerDependencies": {
|
||||||
|
"jspsych": ">=7.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@jspsych/config": "^1.0.0",
|
||||||
|
"@jspsych/test-utils": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
3
packages/extension-mouse-tracking/rollup.config.mjs
Normal file
3
packages/extension-mouse-tracking/rollup.config.mjs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { makeRollupConfig } from "@jspsych/config/rollup";
|
||||||
|
|
||||||
|
export default makeRollupConfig("jsPsychExtensionMouseTracking");
|
104
packages/extension-mouse-tracking/src/index.ts
Normal file
104
packages/extension-mouse-tracking/src/index.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { JsPsych, JsPsychExtension, JsPsychExtensionInfo } from "jspsych";
|
||||||
|
|
||||||
|
interface InitializeParameters {
|
||||||
|
/**
|
||||||
|
* The minimum time between mouse samples. If mouse events occur more rapidly than this limit, they will
|
||||||
|
* not be recorded. Use this if you want to keep the data files smaller and don't need high resolution
|
||||||
|
* tracking data. The default value of 0 means that all events will be recorded.
|
||||||
|
* @default 0
|
||||||
|
*/
|
||||||
|
minimum_sample_time: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnStartParameters {
|
||||||
|
/**
|
||||||
|
* An array of string selectors. The selectors should identify one unique element on the page.
|
||||||
|
* The DOMRect of the element will be stored in the data.
|
||||||
|
*/
|
||||||
|
targets: Array<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MouseTrackingExtension implements JsPsychExtension {
|
||||||
|
static info: JsPsychExtensionInfo = {
|
||||||
|
name: "mouse-tracking",
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(private jsPsych: JsPsych) {}
|
||||||
|
|
||||||
|
private domObserver: MutationObserver;
|
||||||
|
private currentTrialData: Array<object>;
|
||||||
|
private currentTrialTargets: Map<string, DOMRect>;
|
||||||
|
private currentTrialSelectors: Array<string>;
|
||||||
|
private currentTrialStartTime: number;
|
||||||
|
private minimumSampleTime: number;
|
||||||
|
private lastSampleTime: number;
|
||||||
|
|
||||||
|
initialize = ({ minimum_sample_time = 0 }: InitializeParameters): Promise<void> => {
|
||||||
|
this.domObserver = new MutationObserver(this.mutationObserverCallback);
|
||||||
|
this.minimumSampleTime = minimum_sample_time;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
on_start = (params: OnStartParameters): void => {
|
||||||
|
this.currentTrialData = [];
|
||||||
|
this.currentTrialTargets = new Map();
|
||||||
|
this.currentTrialSelectors = params.targets;
|
||||||
|
this.lastSampleTime = null;
|
||||||
|
|
||||||
|
this.domObserver.observe(this.jsPsych.getDisplayElement(), { childList: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
on_load = () => {
|
||||||
|
// set current trial start time
|
||||||
|
this.currentTrialStartTime = performance.now();
|
||||||
|
|
||||||
|
// start data collection
|
||||||
|
window.addEventListener("mousemove", this.mouseEventHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
on_finish = () => {
|
||||||
|
this.domObserver.disconnect();
|
||||||
|
|
||||||
|
window.removeEventListener("mousemove", this.mouseEventHandler);
|
||||||
|
|
||||||
|
return {
|
||||||
|
mouse_tracking_data: this.currentTrialData,
|
||||||
|
mouse_tracking_targets: this.currentTrialTargets,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
private mouseEventHandler = (e) => {
|
||||||
|
const x = e.x;
|
||||||
|
const y = e.y;
|
||||||
|
|
||||||
|
const event_time = performance.now();
|
||||||
|
const t = Math.round(event_time - this.currentTrialStartTime);
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.lastSampleTime === null ||
|
||||||
|
event_time - this.lastSampleTime >= this.minimumSampleTime
|
||||||
|
) {
|
||||||
|
this.lastSampleTime = event_time;
|
||||||
|
this.currentTrialData.push({ x, y, t });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private mutationObserverCallback = (mutationsList, observer) => {
|
||||||
|
for (const selector of this.currentTrialSelectors) {
|
||||||
|
if (!this.currentTrialTargets[selector]) {
|
||||||
|
if (this.jsPsych.getDisplayElement().querySelector(selector)) {
|
||||||
|
var coords = this.jsPsych
|
||||||
|
.getDisplayElement()
|
||||||
|
.querySelector(selector)
|
||||||
|
.getBoundingClientRect();
|
||||||
|
this.currentTrialTargets[selector] = coords;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MouseTrackingExtension;
|
7
packages/extension-mouse-tracking/tsconfig.json
Normal file
7
packages/extension-mouse-tracking/tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"extends": "@jspsych/config/tsconfig.core.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "."
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user