jsPsych/examples/webgazer.html
Becky Gilbert db754538b7
Convert plugins to classes and update examples (#2078)
* modularize plugins: edit index.ts and example files (WIP)

* continue modularizing plugins: edit index.ts and example files (WIP)

* continue modularizing plugins: edit index.ts and example files (WIP)

* continue modularizing plugins and example files, make info static in plugin classes

* add preload flag to plugin info, fix a few parameterType values

* change preload flags in plugin info from audio/image/video strings to boolean

* convert more plugins and example files

* convert more plugins/examples, sync with webgazer branch plugins/examples (not working on this branch)

* remove preload flag from info, change to ParameterType, change to "ALL_KEYS"/"NO_KEYS", change KEY type to KEYS for array params

* remove descriptions from plugin info, fix some ALL_KEYS/NO_KEYS errors

* remove descriptions and add pretty names to plugin info

* remove/edit comments re ALL_KEYS/NO_KEYS and TS errors

* fix some preload plugin errors and convert example file (plugin still not working due to getAutoPreloadList)

* convert RDK plugin and example file

* convert preload plugin and example, add JsPsych getTimelineDescription method for auto-preloading (still not working for audio due to getAudioBuffer

* fix jsPsych getTimelineDescription method so that it does recursive search

* add image and video preloading to plugin examples

* Merge branch 'modularization' into modularization-plugins

* add tests for reconstruction

* fix timeline array getter method: add private timelineDescription var, set to timeline array in run(), rename getTimelineDescription to getTimeline

* changes in response to PR review: fix JsDoc comments, fix array: true in param info, change HTML string param types, add JsDoc author/file/see docs for all plugin classes, switch to @ts-expect-error. Thanks @bjoluc!

* fix JsDoc comments for plugin classes and preload trials parameter

* change preload type to boolean in ParameterInfo interface, and add `preload: false` to virtual-chinrest item_path image parameter

* All my tests except for preload plugin (will do that tomorrow)

* minor fixes to reconstruction tests

* Update preload plugin tests

* Finish test conversion

* switch to arrow functions to fix this keyword errors in plugins, add audio preloading into plugin example files, fix typos

* convert non-plugin example files (WIP, not tested)

* Fix allow_held_keys -> allow_held_key parameter in virtual-chinrest plugin

* Fix `keyboardListener` type in serial-reaction-time plugin

* type fixes for RDK, simplifying `correctOrNot()` function

* fixed ["ALL_KEYS"] => "ALL_KEYS" for iat plugins and tests

* Build jspsych packages before everything else

Dependent builds were previously failing due to missing type definitions

* Remove console.log from html-keyboard-response tests

I think I accidentially committed it.

* fix the delayed start to animation bug (#1885)

* round all RTs to nearest int (#2108)

* fixes and tests #1900 - IAT parameter problems

* finish converting/testing example files, add init settings, add audio preloading, fix errors

* fix progress-bar timeline to demo an example where auto-updating the progress bar works well

* Revert "round all RTs to nearest int (#2108)"

This reverts commit f53145d2e3.

* change how delayed timeline variables are implemented

* use static for generate_stimulus method so that it can be called on the vsl-grid-scene class

* fix external-html plugin and example (switch to arrow function for proper this context, fix incorrect parameter name)

* remove outdated TO DO comments

Co-authored-by: bjoluc <mail@bjoluc.de>
Co-authored-by: Josh de Leeuw <josh.deleeuw@gmail.com>
2021-09-08 09:44:53 -04:00

175 lines
6.2 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<script src="../packages/jspsych/dist/index.browser.js"></script>
<script src="../packages/plugin-html-keyboard-response/dist/index.browser.js"></script>
<script src="../packages/plugin-html-button-response/dist/index.browser.js"></script>
<script src="../packages/plugin-webgazer-init-camera/dist/index.browser.js"></script>
<script src="../packages/plugin-webgazer-calibrate/dist/index.browser.js"></script>
<script src="../packages/plugin-webgazer-validate/dist/index.browser.js"></script>
<script src="js/webgazer/webgazer.js"></script>
<script src="../packages/extension-webgazer/dist/index.browser.js"></script>
<link rel="stylesheet" href="../packages/jspsych/css/jspsych.css" />
<style>
.jspsych-content {
max-width: 100%;
}
</style>
</head>
<body></body>
<script>
var jsPsych = initJsPsych({
extensions: [
{type: jsPsychExtensionWebgazer}
]
});
var camera_instructions = {
type: jsPsychHtmlButtonResponse,
stimulus: `
<p>This experiment uses your camera for eye tracking.</p>
<p>In order to participate you must allow the experiment to use your camera.</p>
<p>You will be prompted to do this on the next screen.</p>
<p>If you do not want to permit the experiment to use your camera, please close the page.</p>
`,
choices: ['Click to begin'],
post_trial_gap: 1000
};
var init_camera = {
type: jsPsychWebgazerInitCamera
};
var calibration_instructions = {
type: jsPsychHtmlButtonResponse,
stimulus: `
<p>Great! Now the eye tracker will be calibrated to translate the image of your eyes from the webcam to a location on your screen.</p>
<p>To do this, you need to click a series of dots.</p>
<p>Keep your head still, and click on each dot as it appears. Look at the dot as you click it.</p>
`,
choices: ['Click to begin'],
post_trial_gap: 1000
};
var calibration = {
type: jsPsychWebgazerCalibrate,
calibration_points: [[50,50], [25,25], [25,75], [75,25], [75,75]],
//calibration_points: [[10,10],[10,30],[10,50],[10,70],[10,90],[30,10],[30,30],[30,50],[30,70],[30,90],[50,10],[50,30],[50,50],[50,70],[50,90],[70,10],[70,30],[70,50],[70,70],[70,90],[90,10],[90,30],[90,50],[90,70],[90,90]],
// calibration_points: [
// [10,10],[10,50],[10,90],
// [30,10],[30,50],[30,90],
// [40,10],[40,30],[40,40],[40,45],[40,50],[40,55],[40,60],[40,70],[40,90],
// [50,10],[50,30],[50,40],[50,45],[50,50],[50,55],[50,60],[50,70],[50,90],
// [60,10],[60,30],[60,40],[60,45],[60,50],[60,55],[60,60],[60,70],[60,90],
// [70,10],[70,50],[70,90],
// [90,10],[90,50],[90,90]],
repetitions_per_point: 2,
randomize_calibration_order: true,
};
var validation_instructions = {
type: jsPsychHtmlButtonResponse,
stimulus: `
<p>Let's see how accurate the eye tracking is. </p>
<p>Keep your head still, and move your eyes to focus on each dot as it appears.</p>
<p>You do not need to click on the dots. Just move your eyes to look at the dots.</p>
`,
choices: ['Click to begin'],
post_trial_gap: 1000
};
var validation = {
type: jsPsychWebgazerValidate,
validation_points: [[25,25], [25,75], [75,25], [75,75]],
show_validation_data: true
};
var task_instructions = {
type: jsPsychHtmlButtonResponse,
stimulus: `
<p>We're ready for the task now.</p>
<p>You'll see an arrow symbol (⬅ or ➡) appear on the screen.</p>
<p>Your job is to press A if ⬅ appears, and L if ➡ appears.</p>
<p>This will repeat 8 times.</p>
`,
choices: ['I am ready!'],
post_trial_gap: 1000
};
var fixation = {
type: jsPsychHtmlKeyboardResponse,
stimulus: '<p style="font-size:40px;">+</p>',
choices: "NO_KEYS",
trial_duration: 500
};
var trial = {
type: jsPsychHtmlKeyboardResponse,
stimulus: function () {
return(
`<div style="position: relative; width: 400px; height: 400px;">
<div style="position: absolute; top:${jsPsych.timelineVariable('top', true)}%; left: ${jsPsych.timelineVariable('left', true)}%">
<span id="arrow-target" style="font-size: 40px; transform: translate(-50%, -50%);">${jsPsych.timelineVariable('direction', true) == 'left' ? '⬅' : '➡'}</span>
</div>
</div>`
)
},
choices: ['a', 'l'],
post_trial_gap: 750,
data: {
top: jsPsych.timelineVariable('top'),
left: jsPsych.timelineVariable('left')
},
extensions: [
{type: jsPsychExtensionWebgazer, params: {targets: ['#arrow-target']}}
]
};
var params = [
{ left: 0, top: 0, direction: 'left' },
{ left: 100, top: 0, direction: 'left' },
{ left: 0, top: 100, direction: 'left' },
{ left: 100, top: 100, direction: 'left' },
{ left: 0, top: 0, direction: 'right' },
{ left: 100, top: 0, direction: 'right' },
{ left: 0, top: 100, direction: 'right' },
{ left: 100, top: 100, direction: 'right' },
];
var trial_proc = {
timeline: [fixation, trial],
timeline_variables: params,
randomize_order: true
};
var done = {
type: jsPsychHtmlButtonResponse,
choices: ['CSV', 'JSON'],
stimulus: `<p>Done!</p><p>If you'd like to download a copy of the data to explore, click the format you'd like below</p>`,
on_finish: function(data){
if(data.response == 0){
jsPsych.data.get().localSave('csv','webgazer-sample-data.csv');
}
if(data.response == 1){
jsPsych.data.get().localSave('json', 'webgazer-sample-data.json');
}
}
};
var timeline = [];
timeline.push(camera_instructions);
timeline.push(init_camera);
timeline.push(calibration_instructions);
timeline.push(calibration);
timeline.push(validation_instructions);
timeline.push(validation);
timeline.push(task_instructions);
timeline.push(trial_proc);
timeline.push(done);
jsPsych.run(timeline);
</script>
</html>