mirror of
https://github.com/jspsych/jsPsych.git
synced 2025-05-12 08:38:11 +00:00
2203 lines
89 KiB
HTML
Executable File
2203 lines
89 KiB
HTML
Executable File
|
|
<!doctype html>
|
|
<html lang="en" class="no-js">
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
|
|
|
|
|
|
|
|
<link rel="canonical" href="https://www.jspsych.org/7.1/overview/eye-tracking/">
|
|
|
|
<link rel="icon" href="../../img/jspsych-favicon.png">
|
|
<meta name="generator" content="mkdocs-1.2.2, mkdocs-material-7.2.4">
|
|
|
|
|
|
|
|
<title>Eye Tracking - jsPsych</title>
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../../assets/stylesheets/main.f7f47774.min.css">
|
|
|
|
|
|
<link rel="stylesheet" href="../../assets/stylesheets/palette.3f5d1f46.min.css">
|
|
|
|
|
|
|
|
<meta name="theme-color" content="#4cae4f">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback">
|
|
<style>:root{--md-text-font-family:"Roboto";--md-code-font-family:"Roboto Mono"}</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script>window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)},ga.l=+new Date,ga("create","UA-50563838-1","auto"),ga("set","anonymizeIp",!0),ga("send","pageview"),document.addEventListener("DOMContentLoaded",function(){document.forms.search&&document.forms.search.query.addEventListener("blur",function(){var e;this.value&&(e=document.location.pathname,ga("send","pageview",e+"?q="+this.value))}),"undefined"!=typeof location$&&location$.subscribe(function(e){ga("send","pageview",e.pathname)})})</script>
|
|
<script async src="https://www.google-analytics.com/analytics.js"></script>
|
|
|
|
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<body dir="ltr" data-md-color-scheme="" data-md-color-primary="green" data-md-color-accent="orange">
|
|
|
|
|
|
<script>function __prefix(e){return new URL("../..",location).pathname+"."+e}function __get(e,t=localStorage){return JSON.parse(t.getItem(__prefix(e)))}</script>
|
|
|
|
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
|
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
|
<label class="md-overlay" for="__drawer"></label>
|
|
<div data-md-component="skip">
|
|
|
|
|
|
<a href="#eye-tracking" class="md-skip">
|
|
Skip to content
|
|
</a>
|
|
|
|
</div>
|
|
<div data-md-component="announce">
|
|
|
|
</div>
|
|
|
|
<header class="md-header" data-md-component="header">
|
|
<nav class="md-header__inner md-grid" aria-label="Header">
|
|
<a href="../.." title="jsPsych" class="md-header__button md-logo" aria-label="jsPsych" data-md-component="logo">
|
|
|
|
<img src="../../img/jspsych-logo-no-text-mono.svg" alt="logo">
|
|
|
|
</a>
|
|
<label class="md-header__button md-icon" for="__drawer">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z"/></svg>
|
|
</label>
|
|
<div class="md-header__title" data-md-component="header-title">
|
|
<div class="md-header__ellipsis">
|
|
<div class="md-header__topic">
|
|
<span class="md-ellipsis">
|
|
jsPsych
|
|
</span>
|
|
</div>
|
|
<div class="md-header__topic" data-md-component="header-topic">
|
|
<span class="md-ellipsis">
|
|
|
|
Eye Tracking
|
|
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<label class="md-header__button md-icon" for="__search">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
|
|
</label>
|
|
|
|
<div class="md-search" data-md-component="search" role="dialog">
|
|
<label class="md-search__overlay" for="__search"></label>
|
|
<div class="md-search__inner" role="search">
|
|
<form class="md-search__form" name="search">
|
|
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
|
<label class="md-search__icon md-icon" for="__search">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z"/></svg>
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
|
|
</label>
|
|
<nav class="md-search__options" aria-label="Search">
|
|
|
|
<button type="reset" class="md-search__icon md-icon" aria-label="Clear" tabindex="-1">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
|
|
</button>
|
|
</nav>
|
|
|
|
</form>
|
|
<div class="md-search__output">
|
|
<div class="md-search__scrollwrap" data-md-scrollfix>
|
|
<div class="md-search-result" data-md-component="search-result">
|
|
<div class="md-search-result__meta">
|
|
Initializing search
|
|
</div>
|
|
<ol class="md-search-result__list"></ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="md-header__source">
|
|
|
|
<a href="https://github.com/jspsych/jsPsych/" title="Go to repository" class="md-source" data-md-component="source">
|
|
<div class="md-source__icon md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
|
|
</div>
|
|
<div class="md-source__repository">
|
|
jspsych/jspsych
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
</nav>
|
|
</header>
|
|
|
|
<div class="md-container" data-md-component="container">
|
|
|
|
|
|
|
|
|
|
<main class="md-main" data-md-component="main">
|
|
<div class="md-main__inner md-grid">
|
|
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
|
|
|
|
|
|
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
|
|
<label class="md-nav__title" for="__drawer">
|
|
<a href="../.." title="jsPsych" class="md-nav__button md-logo" aria-label="jsPsych" data-md-component="logo">
|
|
|
|
<img src="../../img/jspsych-logo-no-text-mono.svg" alt="logo">
|
|
|
|
</a>
|
|
jsPsych
|
|
</label>
|
|
|
|
<div class="md-nav__source">
|
|
|
|
<a href="https://github.com/jspsych/jsPsych/" title="Go to repository" class="md-source" data-md-component="source">
|
|
<div class="md-source__icon md-icon">
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
|
|
</div>
|
|
<div class="md-source__repository">
|
|
jspsych/jspsych
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../.." class="md-nav__link">
|
|
Introduction
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2" type="checkbox" id="__nav_2" >
|
|
|
|
<label class="md-nav__link" for="__nav_2">
|
|
Tutorials
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Tutorials" data-md-level="1">
|
|
<label class="md-nav__title" for="__nav_2">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Tutorials
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../tutorials/hello-world/" class="md-nav__link">
|
|
The Basics: Hello World
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../tutorials/rt-task/" class="md-nav__link">
|
|
Demo Experiment: Simple Reaction Time Task
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../tutorials/video-tutorials/" class="md-nav__link">
|
|
Video Tutorials
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3" type="checkbox" id="__nav_3" checked>
|
|
|
|
<label class="md-nav__link" for="__nav_3">
|
|
Overview
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Overview" data-md-level="1">
|
|
<label class="md-nav__title" for="__nav_3">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Overview
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../timeline/" class="md-nav__link">
|
|
Creating an Experiment: The Timeline
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../plugins/" class="md-nav__link">
|
|
Plugins
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../extensions/" class="md-nav__link">
|
|
Extensions
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../dynamic-parameters/" class="md-nav__link">
|
|
Dynamic Parameters
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../style/" class="md-nav__link">
|
|
Controlling Visual Appearance
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../data/" class="md-nav__link">
|
|
Data Storage, Aggregation, and Manipulation
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../simulation/" class="md-nav__link">
|
|
Simulation Modes
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../running-experiments/" class="md-nav__link">
|
|
Running Experiments
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../experiment-options/" class="md-nav__link">
|
|
Experiment Settings
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../events/" class="md-nav__link">
|
|
Events
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../record-browser-interactions/" class="md-nav__link">
|
|
Record Browser Interactions
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../media-preloading/" class="md-nav__link">
|
|
Media Preloading
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../fullscreen/" class="md-nav__link">
|
|
Fullscreen Experiments
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--active">
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc">
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__link md-nav__link--active" for="__toc">
|
|
Eye Tracking
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
|
|
<a href="./" class="md-nav__link md-nav__link--active">
|
|
Eye Tracking
|
|
</a>
|
|
|
|
|
|
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__title" for="__toc">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Table of contents
|
|
</label>
|
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#getting-started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="Getting Started">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#load-webgazerjs" class="md-nav__link">
|
|
Load webgazer.js
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#load-the-jspsych-webgazer-extension" class="md-nav__link">
|
|
Load the jsPsych webgazer extension
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#initialize-the-camera" class="md-nav__link">
|
|
Initialize the camera
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#calibration" class="md-nav__link">
|
|
Calibration
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#validation" class="md-nav__link">
|
|
Validation
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#adding-eye-tracking-to-a-trial" class="md-nav__link">
|
|
Adding eye tracking to a trial
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#tips-for-improving-data-quality" class="md-nav__link">
|
|
Tips for Improving Data Quality
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#example" class="md-nav__link">
|
|
Example
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../exclude-browser/" class="md-nav__link">
|
|
Exclude Participants Based on Browser Features
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../progress-bar/" class="md-nav__link">
|
|
Automatic Progress Bar
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../prolific/" class="md-nav__link">
|
|
Integrating with Prolific
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../mturk/" class="md-nav__link">
|
|
Integrating with Mechanical Turk
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../browser-device-support/" class="md-nav__link">
|
|
Browser and Device Support
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../timing-accuracy/" class="md-nav__link">
|
|
Timing Accuracy
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" type="checkbox" id="__nav_4" >
|
|
|
|
<label class="md-nav__link" for="__nav_4">
|
|
Reference
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Reference" data-md-level="1">
|
|
<label class="md-nav__title" for="__nav_4">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Reference
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../reference/jspsych/" class="md-nav__link">
|
|
jsPsych
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../reference/jspsych-data/" class="md-nav__link">
|
|
jsPsych.data
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../reference/jspsych-randomization/" class="md-nav__link">
|
|
jsPsych.randomization
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../reference/jspsych-turk/" class="md-nav__link">
|
|
jsPsych.turk
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../reference/jspsych-pluginAPI/" class="md-nav__link">
|
|
jsPsych.pluginAPI
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5" type="checkbox" id="__nav_5" >
|
|
|
|
<label class="md-nav__link" for="__nav_5">
|
|
Plugins
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Plugins" data-md-level="1">
|
|
<label class="md-nav__title" for="__nav_5">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Plugins
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/list-of-plugins/" class="md-nav__link">
|
|
List of Plugins
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/animation/" class="md-nav__link">
|
|
animation
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/audio-button-response/" class="md-nav__link">
|
|
audio-button-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/audio-keyboard-response/" class="md-nav__link">
|
|
audio-keyboard-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/audio-slider-response/" class="md-nav__link">
|
|
audio-slider-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/browser-check/" class="md-nav__link">
|
|
browser-check
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/call-function/" class="md-nav__link">
|
|
call-function
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/canvas-button-response/" class="md-nav__link">
|
|
canvas-button-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/canvas-keyboard-response/" class="md-nav__link">
|
|
canvas-keyboard-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/canvas-slider-response/" class="md-nav__link">
|
|
canvas-slider-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/categorize-animation/" class="md-nav__link">
|
|
categorize-animation
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/categorize-html/" class="md-nav__link">
|
|
categorize-html
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/categorize-image/" class="md-nav__link">
|
|
categorize-image
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/cloze/" class="md-nav__link">
|
|
cloze
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/external-html/" class="md-nav__link">
|
|
external-html
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/free-sort/" class="md-nav__link">
|
|
free-sort
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/fullscreen/" class="md-nav__link">
|
|
fullscreen
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/html-audio-response/" class="md-nav__link">
|
|
html-audio-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/html-button-response/" class="md-nav__link">
|
|
html-button-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/html-keyboard-response/" class="md-nav__link">
|
|
html-keyboard-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/html-slider-response/" class="md-nav__link">
|
|
html-slider-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/iat-html/" class="md-nav__link">
|
|
iat-html
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/iat-image/" class="md-nav__link">
|
|
iat-image
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/image-button-response/" class="md-nav__link">
|
|
image-button-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/image-keyboard-response/" class="md-nav__link">
|
|
image-keyboard-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/image-slider-response/" class="md-nav__link">
|
|
image-slider-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/initialize-microphone/" class="md-nav__link">
|
|
initialize-microphone
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/instructions/" class="md-nav__link">
|
|
instructions
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/maxdiff/" class="md-nav__link">
|
|
maxdiff
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/preload/" class="md-nav__link">
|
|
preload
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/reconstruction/" class="md-nav__link">
|
|
reconstruction
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/resize/" class="md-nav__link">
|
|
resize
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/same-different-html/" class="md-nav__link">
|
|
same-different-html
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/same-different-image/" class="md-nav__link">
|
|
same-different-image
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/serial-reaction-time/" class="md-nav__link">
|
|
serial-reaction-time
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/serial-reaction-time-mouse/" class="md-nav__link">
|
|
serial-reaction-time-mouse
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/sketchpad/" class="md-nav__link">
|
|
sketchpad
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/survey/" class="md-nav__link">
|
|
survey
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/survey-html-form/" class="md-nav__link">
|
|
survey-html-form
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/survey-likert/" class="md-nav__link">
|
|
survey-likert
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/survey-multi-choice/" class="md-nav__link">
|
|
survey-multi-choice
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/survey-multi-select/" class="md-nav__link">
|
|
survey-multi-select
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/survey-text/" class="md-nav__link">
|
|
survey-text
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/video-button-response/" class="md-nav__link">
|
|
video-button-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/video-keyboard-response/" class="md-nav__link">
|
|
video-keyboard-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/video-slider-response/" class="md-nav__link">
|
|
video-slider-response
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/virtual-chinrest/" class="md-nav__link">
|
|
virtual-chinrest
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/visual-search-circle/" class="md-nav__link">
|
|
visual-search-circle
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/webgazer-calibrate/" class="md-nav__link">
|
|
webgazer-calibrate
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/webgazer-init-camera/" class="md-nav__link">
|
|
webgazer-init-camera
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../plugins/webgazer-validate/" class="md-nav__link">
|
|
webgazer-validate
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_6" type="checkbox" id="__nav_6" >
|
|
|
|
<label class="md-nav__link" for="__nav_6">
|
|
Extensions
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Extensions" data-md-level="1">
|
|
<label class="md-nav__title" for="__nav_6">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Extensions
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../extensions/list-of-extensions/" class="md-nav__link">
|
|
List of Extensions
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../extensions/mouse-tracking/" class="md-nav__link">
|
|
mouse-tracking
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../extensions/webgazer/" class="md-nav__link">
|
|
webgazer
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_7" type="checkbox" id="__nav_7" >
|
|
|
|
<label class="md-nav__link" for="__nav_7">
|
|
Developers
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Developers" data-md-level="1">
|
|
<label class="md-nav__title" for="__nav_7">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Developers
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../developers/configuration/" class="md-nav__link">
|
|
Configuration
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../developers/contributing/" class="md-nav__link">
|
|
Contributing to jsPsych
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../developers/plugin-development/" class="md-nav__link">
|
|
Plugin Development
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../developers/extension-development/" class="md-nav__link">
|
|
Extension Development
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_8" type="checkbox" id="__nav_8" >
|
|
|
|
<label class="md-nav__link" for="__nav_8">
|
|
Support
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="Support" data-md-level="1">
|
|
<label class="md-nav__title" for="__nav_8">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Support
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../support/support/" class="md-nav__link">
|
|
Getting Help
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../support/migration-v7/" class="md-nav__link">
|
|
Migrating from 6.x to 7.x
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item md-nav__item--nested">
|
|
|
|
|
|
<input class="md-nav__toggle md-toggle" data-md-toggle="__nav_9" type="checkbox" id="__nav_9" >
|
|
|
|
<label class="md-nav__link" for="__nav_9">
|
|
About
|
|
<span class="md-nav__icon md-icon"></span>
|
|
</label>
|
|
<nav class="md-nav" aria-label="About" data-md-level="1">
|
|
<label class="md-nav__title" for="__nav_9">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
About
|
|
</label>
|
|
<ul class="md-nav__list" data-md-scrollfix>
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../about/about/" class="md-nav__link">
|
|
About jsPsych
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="md-nav__item">
|
|
<a href="../../about/license/" class="md-nav__link">
|
|
License
|
|
</a>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</li>
|
|
|
|
|
|
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
|
<div class="md-sidebar__scrollwrap">
|
|
<div class="md-sidebar__inner">
|
|
|
|
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<label class="md-nav__title" for="__toc">
|
|
<span class="md-nav__icon md-icon"></span>
|
|
Table of contents
|
|
</label>
|
|
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#getting-started" class="md-nav__link">
|
|
Getting Started
|
|
</a>
|
|
|
|
<nav class="md-nav" aria-label="Getting Started">
|
|
<ul class="md-nav__list">
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#load-webgazerjs" class="md-nav__link">
|
|
Load webgazer.js
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#load-the-jspsych-webgazer-extension" class="md-nav__link">
|
|
Load the jsPsych webgazer extension
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#initialize-the-camera" class="md-nav__link">
|
|
Initialize the camera
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#calibration" class="md-nav__link">
|
|
Calibration
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#validation" class="md-nav__link">
|
|
Validation
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#adding-eye-tracking-to-a-trial" class="md-nav__link">
|
|
Adding eye tracking to a trial
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#tips-for-improving-data-quality" class="md-nav__link">
|
|
Tips for Improving Data Quality
|
|
</a>
|
|
|
|
</li>
|
|
|
|
<li class="md-nav__item">
|
|
<a href="#example" class="md-nav__link">
|
|
Example
|
|
</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="md-content" data-md-component="content">
|
|
<article class="md-content__inner md-typeset">
|
|
|
|
|
|
<a href="https://github.com/jspsych/jsPsych/edit/master/docs/overview/eye-tracking.md" title="Edit this page" class="md-content__button md-icon">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z"/></svg>
|
|
</a>
|
|
|
|
|
|
<h1 id="eye-tracking">Eye Tracking<a class="headerlink" href="#eye-tracking" title="Permanent link">¶</a></h1>
|
|
<p>jsPsych supports eye tracking through the <a href="https://webgazer.cs.brown.edu/">WebGazer</a> library. WebGazer uses computer vision techniques to identify features of the participant's eyes via a webcam and predicts gaze location. The system is calibrated by having the participant click on or look at known locations on the screen. These locations are linked to eye features. Gaze location is predicted using regression.</p>
|
|
<h2 id="getting-started">Getting Started<a class="headerlink" href="#getting-started" title="Permanent link">¶</a></h2>
|
|
<h3 id="load-webgazerjs">Load webgazer.js<a class="headerlink" href="#load-webgazerjs" title="Permanent link">¶</a></h3>
|
|
<p>The <a href="https://webgazer.cs.brown.edu/#download">official version of WebGazer</a> is currently <strong>not</strong> supported by jsPsych. Our <a href="https://github.com/jspsych/WebGazer">fork of the library</a> contains some minor improvements aimed at the kind of experiments that jsPsych is typically used for, e.g., situations in which the timing of display screens needs to be accurate. </p>
|
|
<p>You must include the <code>webgazer.js</code> file in your experiment via a <code><script></code> tag.
|
|
However, the <code>webgazer.js</code> file is not part of any of the jsPsych NPM packages and is therefore not available via the unpkg.com CDN.
|
|
Instead, it can be found on the jsdelivr.net CDN at: "https://cdn.jsdelivr.net/gh/jspsych/jspsych@jspsych@7.1.2/examples/js/webgazer/webgazer.js".</p>
|
|
<div class="highlight"><pre><span></span><code><span class="p"><</span><span class="nt">head</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/jspsych@7.1.2"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://cdn.jsdelivr.net/gh/jspsych/jspsych@7.1.2/examples/js/webgazer/webgazer.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"></</span><span class="nt">head</span><span class="p">></span>
|
|
</code></pre></div>
|
|
<div class="admonition note">
|
|
<p class="admonition-title">Note</p>
|
|
</div>
|
|
<p>A copy of our forked <code>webgazer.js</code> file is also included in the jsPsych release, in the <code>/examples/js/webgazer</code> folder.
|
|
So if you prefer to download and host all of your jsPsych files (i.e. <a href="../../tutorials/hello-world/#option-2-download-and-host-jspsych">set-up option 2</a> in the Hello World tutorial), then another option is to load that file rather than using the jsdelivr link above.
|
|
Assuming you downloaded the release and copied the <code>webgazer.js</code> file into a folder called <code>js/webgazer</code> in your root project directory, then you would load the file like this:
|
|
<div class="highlight"><pre><span></span><code><span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"js/webgazer/webgazer.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
</code></pre></div></p>
|
|
<h3 id="load-the-jspsych-webgazer-extension">Load the jsPsych webgazer extension<a class="headerlink" href="#load-the-jspsych-webgazer-extension" title="Permanent link">¶</a></h3>
|
|
<p>The <a href="../../extensions/webgazer/">webgazer extension</a> adds functionality to jsPsych for interacting with webgazer. Load it like you would a plugin file.</p>
|
|
<div class="highlight"><pre><span></span><code><span class="p"><</span><span class="nt">head</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/jspsych@7.1.2"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://cdn.jsdelivr.net/gh/jspsych/jspsych@7.1.2/examples/js/webgazer/webgazer.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/extension-webgazer@1.0.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"></</span><span class="nt">head</span><span class="p">></span>
|
|
</code></pre></div>
|
|
<p>To use the WebGazer extension in an experiment, include it in the list of extensions passed to <code>initJsPsych()</code></p>
|
|
<div class="highlight"><pre><span></span><code><span class="nx">initJsPsych</span><span class="p">({</span>
|
|
<span class="nx">extensions</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychExtensionWebgazer</span><span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">})</span>
|
|
</code></pre></div>
|
|
<h3 id="initialize-the-camera">Initialize the camera<a class="headerlink" href="#initialize-the-camera" title="Permanent link">¶</a></h3>
|
|
<p>To help the participant position their face correctly for eye tracking you can use the <a href="../../plugins/webgazer-init-camera/">webgazer-init-camera plugin</a>. This will show the participant what the camera sees, including facial feature landmarks, and prevent the participant from continuing until their face is in good position for eye tracking. This plugin will also trigger the experiment to request permission to access the user's webcam if it hasn't already been granted.</p>
|
|
<div class="highlight"><pre><span></span><code><span class="kd">var</span> <span class="nx">init_camera_trial</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychWebgazerInitCamera</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<h3 id="calibration">Calibration<a class="headerlink" href="#calibration" title="Permanent link">¶</a></h3>
|
|
<p>To calibrate WebGazer, you can use the <a href="../../plugins/webgazer-calibrate/">webgazer-calibrate plugin</a>. This plugin allows you to specify a set of points on the screen for calibration and to choose the method for calibrating -- either clicking on each point or simply fixating on each point. The location of calibration points is specified in percentages, e.g., <code>[25,50]</code> will result in a point that is 25% of the width of the screen from the left edge and 50% of the height of the screen from the top edge. Options for controlling other details of the calibration are explained in the <a href="../../plugins/webgazer-calibrate/">documentation for the plugin</a>.</p>
|
|
<p>Note that instructions are not included in the calibration plugin, so you'll likely want to use a different plugin (e.g., <code>html-button-response</code>) to display instructions prior to running the calibration. </p>
|
|
<div class="highlight"><pre><span></span><code><span class="kd">var</span> <span class="nx">calibration_trial</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychWebgazerCalibrate</span><span class="p">,</span>
|
|
<span class="nx">calibration_points</span><span class="o">:</span> <span class="p">[[</span><span class="mf">25</span><span class="p">,</span><span class="mf">50</span><span class="p">],</span> <span class="p">[</span><span class="mf">50</span><span class="p">,</span><span class="mf">50</span><span class="p">],</span> <span class="p">[</span><span class="mf">75</span><span class="p">,</span><span class="mf">50</span><span class="p">],</span> <span class="p">[</span><span class="mf">50</span><span class="p">,</span><span class="mf">25</span><span class="p">],</span> <span class="p">[</span><span class="mf">50</span><span class="p">,</span><span class="mf">75</span><span class="p">]],</span>
|
|
<span class="nx">calibration_mode</span><span class="o">:</span> <span class="s1">'click'</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<h3 id="validation">Validation<a class="headerlink" href="#validation" title="Permanent link">¶</a></h3>
|
|
<p>To measure the accuracy and precision of the calibration, you can use the <a href="../../plugins/webgazer-validate/">webgazer-vaidate plugin</a>. Like the calibration plugin, you can specify a list of points to perform validation on. Here you can specify the points as either percentages or in terms of the distance from the center of the screen in pixels. Which mode you use will probably depend on how you are defining your stimuli throughout the experiment. You can also specify the radius of tolerance around each point, and the plugin will calculate the percentage of measured gaze samples within that radius. This is a potentially useful heuristic for deciding whether or not to calibrate again. Options for controlling other details of the validation are explained in the <a href="../../plugins/webgazer-validate/">documentation for the plugin</a>.</p>
|
|
<div class="highlight"><pre><span></span><code><span class="kd">var</span> <span class="nx">validation_trial</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychWebgazerValidate</span><span class="p">,</span>
|
|
<span class="nx">validation_points</span><span class="o">:</span> <span class="p">[[</span><span class="o">-</span><span class="mf">200</span><span class="p">,</span><span class="mf">200</span><span class="p">],</span> <span class="p">[</span><span class="mf">200</span><span class="p">,</span><span class="mf">200</span><span class="p">],[</span><span class="o">-</span><span class="mf">200</span><span class="p">,</span><span class="o">-</span><span class="mf">200</span><span class="p">],[</span><span class="mf">200</span><span class="p">,</span><span class="o">-</span><span class="mf">200</span><span class="p">]],</span>
|
|
<span class="nx">validation_point_coordinates</span><span class="o">:</span> <span class="s1">'center-offset-pixels'</span><span class="p">,</span>
|
|
<span class="nx">roi_radius</span><span class="o">:</span> <span class="mf">100</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>The validation procedure stores the raw gaze data for each validation point, the computed average offset from each validation point, the percentage of samples within the <code>roi_radius</code> for each validation point, and the number of samples collected per second.</p>
|
|
<div class="highlight"><pre><span></span><code><span class="p">{</span>
|
|
<span class="nx">raw_gaze</span><span class="o">:</span> <span class="p">[...],</span>
|
|
<span class="nx">percent_in_roi</span><span class="o">:</span> <span class="p">[...],</span>
|
|
<span class="nx">average_offset</span><span class="o">:</span> <span class="p">[...],</span>
|
|
<span class="nx">samples_per_sec</span><span class="o">:</span> <span class="p">...</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>We recommend performing calibration and validation periodically throughout your experiment.</p>
|
|
<h3 id="adding-eye-tracking-to-a-trial">Adding eye tracking to a trial<a class="headerlink" href="#adding-eye-tracking-to-a-trial" title="Permanent link">¶</a></h3>
|
|
<p>To enable eye tracking for a trial in your experiment, you can simply add the WebGazer extension to the trial.</p>
|
|
<div class="highlight"><pre><span></span><code><span class="kd">var</span> <span class="nx">trial</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychHtmlKeyboardResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="s1">'<img id="scene" src="my-scene.png"></img>'</span><span class="p">,</span>
|
|
<span class="nx">extensions</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychExtensionWebgazer</span><span class="p">,</span>
|
|
<span class="nx">params</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">targets</span><span class="o">:</span> <span class="p">[</span><span class="s1">'#scene'</span><span class="p">]</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>This will turn on WebGazer at the start of the trial. </p>
|
|
<p>The <code>params</code> property in the <code>extensions</code> declaration allows you to pass in a list of <a href="https://www.w3schools.com/cssref/css_selectors.asp">CSS selector strings</a>. The <a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect">bounding rectangle</a> of the DOM element that matches each selector will be recorded in the data for that trial. This allows for easy alignment of the gaze data and objects on the screen.</p>
|
|
<div class="highlight"><pre><span></span><code><span class="nx">webgazer_targets</span> <span class="o">:</span> <span class="p">{</span>
|
|
<span class="s1">'selector'</span><span class="o">:</span> <span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">y</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">height</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">width</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">top</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">left</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">right</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">bottom</span><span class="o">:</span><span class="p">...}</span>
|
|
<span class="s1">'selector'</span><span class="o">:</span> <span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">y</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">height</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">width</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">top</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">left</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">right</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">bottom</span><span class="o">:</span><span class="p">...}</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
<p>Gaze data will be added to the trial's data under the property <code>webgazer_data</code>. The gaze data is an array of objects. Each object has an <code>x</code>, a <code>y</code>, and a <code>t</code> property. The <code>x</code> and <code>y</code> properties specify the gaze location in pixels and <code>t</code> specifies the time in milliseconds since the start of the trial. Note that establishing the precision and accuracy of these measurements across the variety of web browsers and systems that your experiment participants might be using is quite difficult. For example, different browsers may cause small systematic shifts in the accuracy of <code>t</code> values. </p>
|
|
<div class="highlight"><pre><span></span><code><span class="nx">webgazer_data</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">y</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">t</span><span class="o">:</span> <span class="p">...},</span>
|
|
<span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">y</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">t</span><span class="o">:</span> <span class="p">...},</span>
|
|
<span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">y</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">t</span><span class="o">:</span> <span class="p">...},</span>
|
|
<span class="p">{</span><span class="nx">x</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">y</span><span class="o">:</span> <span class="p">...,</span> <span class="nx">t</span><span class="o">:</span> <span class="p">...}</span>
|
|
<span class="p">]</span>
|
|
</code></pre></div>
|
|
<h2 id="tips-for-improving-data-quality">Tips for Improving Data Quality<a class="headerlink" href="#tips-for-improving-data-quality" title="Permanent link">¶</a></h2>
|
|
<p>These are some anecdotal observations about factors that improve data quality.</p>
|
|
<ol>
|
|
<li>The quality of the camera feed is essential. Good lighting makes a big difference. You may want to encourage participants to perform any eye tracking experiments in a well-lit room.</li>
|
|
<li>Participants need to keep their head relatively still during and after calibration. The calibration is not robust to head movements.</li>
|
|
<li>WebGazer's click-based calibration can be used throughout the experiment. You can turn this on by calling <code>jsPsych.extensions.webgazer.startMouseCalibration()</code> at any point in the experiment. If you use a continue button to advance through the experiment and move the location of the continue button around you can be making small adjustments to the calibration throughout. </li>
|
|
<li>Computing the gaze predictions consumes more computational resources than most other things that jsPsych is typically used for. The sampling rate that WebGazer is able to achieve will depend on the computing power of the participant's device. You may want to ask the participant to close any non-essential software and browser windows prior to completing the experiment. You may also want to check that the sampling rate is sufficiently high as part of validation.</li>
|
|
</ol>
|
|
<p>If you have tips based on your own experience please consider sharing them on our <a href="https://github.com/jspsych/jsPsych/discussions">discussion forum</a> and we'll add to this list!</p>
|
|
<h2 id="example">Example<a class="headerlink" href="#example" title="Permanent link">¶</a></h2>
|
|
<div class="admonition tip">
|
|
<p class="admonition-title">Tip</p>
|
|
<p>Additional example experiments using WebGazer are available in the <strong>/examples</strong> folder of the jsPsych release. See <code>webgazer.html</code>, <code>webgazer_image.html</code>, and <code>webgazer_audio.html</code>. </p>
|
|
</div>
|
|
<div class="admonition example">
|
|
<p class="admonition-title">Example</p>
|
|
<p>Here's an example of putting all of the pieces above together. This example also shows how to use data from the validation to decide whether or not to recalibrate. You can <a href="/demos/eye-tracking-with-webgazer.html" target="_blank">try this experiment here (opens in new tab)</a>.</p>
|
|
<div class="highlight"><pre><span></span><code><span class="cp"><!DOCTYPE html></span>
|
|
<span class="p"><</span><span class="nt">html</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">head</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/jspsych@7.1.2"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/plugin-preload@1.1.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/plugin-html-button-response@1.1.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/plugin-image-keyboard-response@1.1.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/plugin-webgazer-init-camera@1.0.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/plugin-webgazer-calibrate@1.0.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/plugin-webgazer-validate@1.0.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://cdn.jsdelivr.net/gh/jspsych/jspsych@7.1.2/examples/js/webgazer/webgazer.js"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span> <span class="na">src</span><span class="o">=</span><span class="s">"https://unpkg.com/@jspsych/extension-webgazer@1.0.0"</span><span class="p">></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">link</span>
|
|
<span class="na">rel</span><span class="o">=</span><span class="s">"stylesheet"</span>
|
|
<span class="na">href</span><span class="o">=</span><span class="s">"https://unpkg.com/jspsych@7.1.2/css/jspsych.css"</span>
|
|
<span class="p">/></span>
|
|
<span class="p"><</span><span class="nt">style</span><span class="p">></span>
|
|
<span class="p">.</span><span class="nc">jspsych-btn</span> <span class="p">{</span>
|
|
<span class="k">margin-bottom</span><span class="p">:</span> <span class="mi">10</span><span class="kt">px</span><span class="p">;</span>
|
|
<span class="p">}</span>
|
|
<span class="p"></</span><span class="nt">style</span><span class="p">></span>
|
|
<span class="p"></</span><span class="nt">head</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">body</span><span class="p">></</span><span class="nt">body</span><span class="p">></span>
|
|
<span class="p"><</span><span class="nt">script</span><span class="p">></span>
|
|
|
|
<span class="kd">var</span> <span class="nx">jsPsych</span> <span class="o">=</span> <span class="nx">initJsPsych</span><span class="p">({</span>
|
|
<span class="nx">extensions</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span><span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychExtensionWebgazer</span><span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">});</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">preload</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychPreload</span><span class="p">,</span>
|
|
<span class="nx">images</span><span class="o">:</span> <span class="p">[</span><span class="s1">'img/blue.png'</span><span class="p">]</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">camera_instructions</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychHtmlButtonResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="sb">`</span>
|
|
<span class="sb"> <p>In order to participate you must allow the experiment to use your camera.</p></span>
|
|
<span class="sb"> <p>You will be prompted to do this on the next screen.</p></span>
|
|
<span class="sb"> <p>If you do not wish to allow use of your camera, you cannot participate in this experiment.<p></span>
|
|
<span class="sb"> <p>It may take up to 30 seconds for the camera to initialize after you give permission.</p></span>
|
|
<span class="sb"> `</span><span class="p">,</span>
|
|
<span class="nx">choices</span><span class="o">:</span> <span class="p">[</span><span class="s1">'Got it'</span><span class="p">],</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">init_camera</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychWebgazerInitCamera</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">calibration_instructions</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychHtmlButtonResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="sb">`</span>
|
|
<span class="sb"> <p>Now you'll calibrate the eye tracking, so that the software can use the image of your eyes to predict where you are looking.</p></span>
|
|
<span class="sb"> <p>You'll see a series of dots appear on the screen. Look at each dot and click on it.</p></span>
|
|
<span class="sb"> `</span><span class="p">,</span>
|
|
<span class="nx">choices</span><span class="o">:</span> <span class="p">[</span><span class="s1">'Got it'</span><span class="p">],</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">calibration</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychWebgazerCalibrate</span><span class="p">,</span>
|
|
<span class="nx">calibration_points</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">[</span><span class="mf">25</span><span class="p">,</span><span class="mf">25</span><span class="p">],[</span><span class="mf">75</span><span class="p">,</span><span class="mf">25</span><span class="p">],[</span><span class="mf">50</span><span class="p">,</span><span class="mf">50</span><span class="p">],[</span><span class="mf">25</span><span class="p">,</span><span class="mf">75</span><span class="p">],[</span><span class="mf">75</span><span class="p">,</span><span class="mf">75</span><span class="p">]</span>
|
|
<span class="p">],</span>
|
|
<span class="nx">repetitions_per_point</span><span class="o">:</span> <span class="mf">2</span><span class="p">,</span>
|
|
<span class="nx">randomize_calibration_order</span><span class="o">:</span> <span class="kc">true</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">validation_instructions</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychHtmlButtonResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="sb">`</span>
|
|
<span class="sb"> <p>Now we'll measure the accuracy of the calibration.</p></span>
|
|
<span class="sb"> <p>Look at each dot as it appears on the screen.</p></span>
|
|
<span class="sb"> <p style="font-weight: bold;">You do not need to click on the dots this time.</p></span>
|
|
<span class="sb"> `</span><span class="p">,</span>
|
|
<span class="nx">choices</span><span class="o">:</span> <span class="p">[</span><span class="s1">'Got it'</span><span class="p">],</span>
|
|
<span class="nx">post_trial_gap</span><span class="o">:</span> <span class="mf">1000</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">validation</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychWebgazerValidate</span><span class="p">,</span>
|
|
<span class="nx">validation_points</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">[</span><span class="mf">25</span><span class="p">,</span><span class="mf">25</span><span class="p">],[</span><span class="mf">75</span><span class="p">,</span><span class="mf">25</span><span class="p">],[</span><span class="mf">50</span><span class="p">,</span><span class="mf">50</span><span class="p">],[</span><span class="mf">25</span><span class="p">,</span><span class="mf">75</span><span class="p">],[</span><span class="mf">75</span><span class="p">,</span><span class="mf">75</span><span class="p">]</span>
|
|
<span class="p">],</span>
|
|
<span class="nx">roi_radius</span><span class="o">:</span> <span class="mf">200</span><span class="p">,</span>
|
|
<span class="nx">time_to_saccade</span><span class="o">:</span> <span class="mf">1000</span><span class="p">,</span>
|
|
<span class="nx">validation_duration</span><span class="o">:</span> <span class="mf">2000</span><span class="p">,</span>
|
|
<span class="nx">data</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">task</span><span class="o">:</span> <span class="s1">'validate'</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">recalibrate_instructions</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychHtmlButtonResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="sb">`</span>
|
|
<span class="sb"> <p>The accuracy of the calibration is a little lower than we'd like.</p></span>
|
|
<span class="sb"> <p>Let's try calibrating one more time.</p></span>
|
|
<span class="sb"> <p>On the next screen, look at the dots and click on them.<p></span>
|
|
<span class="sb"> `</span><span class="p">,</span>
|
|
<span class="nx">choices</span><span class="o">:</span> <span class="p">[</span><span class="s1">'OK'</span><span class="p">],</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">recalibrate</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">timeline</span><span class="o">:</span> <span class="p">[</span><span class="nx">recalibrate_instructions</span><span class="p">,</span> <span class="nx">calibration</span><span class="p">,</span> <span class="nx">validation_instructions</span><span class="p">,</span> <span class="nx">validation</span><span class="p">],</span>
|
|
<span class="nx">conditional_function</span><span class="o">:</span> <span class="kd">function</span><span class="p">(){</span>
|
|
<span class="kd">var</span> <span class="nx">validation_data</span> <span class="o">=</span> <span class="nx">jsPsych</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">get</span><span class="p">().</span><span class="nx">filter</span><span class="p">({</span><span class="nx">task</span><span class="o">:</span> <span class="s1">'validate'</span><span class="p">}).</span><span class="nx">values</span><span class="p">()[</span><span class="mf">0</span><span class="p">];</span>
|
|
<span class="k">return</span> <span class="nx">validation_data</span><span class="p">.</span><span class="nx">percent_in_roi</span><span class="p">.</span><span class="nx">some</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
|
|
<span class="kd">var</span> <span class="nx">minimum_percent_acceptable</span> <span class="o">=</span> <span class="mf">50</span><span class="p">;</span>
|
|
<span class="k">return</span> <span class="nx">x</span> <span class="o"><</span> <span class="nx">minimum_percent_acceptable</span><span class="p">;</span>
|
|
<span class="p">});</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">data</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="nx">phase</span><span class="o">:</span> <span class="s1">'recalibration'</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">calibration_done</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychHtmlButtonResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="sb">`</span>
|
|
<span class="sb"> <p>Great, we're done with calibration!</p></span>
|
|
<span class="sb"> `</span><span class="p">,</span>
|
|
<span class="nx">choices</span><span class="o">:</span> <span class="p">[</span><span class="s1">'OK'</span><span class="p">]</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">begin</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychHtmlKeyboardResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="sb">`<p>The next screen will show an image to demonstrate adding the webgazer extension to a trial.</p></span>
|
|
<span class="sb"> <p>Just look at the image while eye tracking data is collected. The trial will end automatically.</p></span>
|
|
<span class="sb"> <p>Press any key to start.</p></span>
|
|
<span class="sb"> `</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">trial</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychImageKeyboardResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="s1">'img/blue.png'</span><span class="p">,</span>
|
|
<span class="nx">choices</span><span class="o">:</span> <span class="s2">"NO_KEYS"</span><span class="p">,</span>
|
|
<span class="nx">trial_duration</span><span class="o">:</span> <span class="mf">2000</span><span class="p">,</span>
|
|
<span class="nx">extensions</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychExtensionWebgazer</span><span class="p">,</span>
|
|
<span class="nx">params</span><span class="o">:</span> <span class="p">{</span><span class="nx">targets</span><span class="o">:</span> <span class="p">[</span><span class="s1">'#jspsych-image-keyboard-response-stimulus'</span><span class="p">]}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="kd">var</span> <span class="nx">show_data</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="nx">type</span><span class="o">:</span> <span class="nx">jsPsychHtmlKeyboardResponse</span><span class="p">,</span>
|
|
<span class="nx">stimulus</span><span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
|
|
<span class="kd">var</span> <span class="nx">trial_data</span> <span class="o">=</span> <span class="nx">jsPsych</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">getLastTrialData</span><span class="p">().</span><span class="nx">values</span><span class="p">();</span>
|
|
<span class="kd">var</span> <span class="nx">trial_json</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">trial_data</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="mf">2</span><span class="p">);</span>
|
|
<span class="k">return</span> <span class="sb">`<p style="margin-bottom:0px;"><strong>Trial data:</strong></p></span>
|
|
<span class="sb"> <pre style="margin-top:0px;text-align:left;"></span><span class="si">${</span><span class="nx">trial_json</span><span class="si">}</span><span class="sb"></pre>`</span><span class="p">;</span>
|
|
<span class="p">},</span>
|
|
<span class="nx">choices</span><span class="o">:</span> <span class="s2">"NO_KEYS"</span>
|
|
<span class="p">};</span>
|
|
|
|
<span class="nx">jsPsych</span><span class="p">.</span><span class="nx">run</span><span class="p">([</span>
|
|
<span class="nx">preload</span><span class="p">,</span>
|
|
<span class="nx">camera_instructions</span><span class="p">,</span>
|
|
<span class="nx">init_camera</span><span class="p">,</span>
|
|
<span class="nx">calibration_instructions</span><span class="p">,</span>
|
|
<span class="nx">calibration</span><span class="p">,</span>
|
|
<span class="nx">validation_instructions</span><span class="p">,</span>
|
|
<span class="nx">validation</span><span class="p">,</span>
|
|
<span class="nx">recalibrate</span><span class="p">,</span>
|
|
<span class="nx">calibration_done</span><span class="p">,</span>
|
|
<span class="nx">begin</span><span class="p">,</span>
|
|
<span class="nx">trial</span><span class="p">,</span>
|
|
<span class="nx">show_data</span>
|
|
<span class="p">]);</span>
|
|
|
|
<span class="p"></</span><span class="nt">script</span><span class="p">></span>
|
|
<span class="p"></</span><span class="nt">html</span><span class="p">></span>
|
|
</code></pre></div>
|
|
<p>Below is example data from the image-keyboard-response trial taken from the experiment above. In addition to the standard data that is collected for this plugin, you can see the additional <code>webgazer_data</code> and <code>webgazer_targets</code> arrays. The <code>webgazer_data</code> shows 21 gaze location estimates during the 1-second image presentation. The <code>webgazer_targets</code> array shows that there was one target, the image-keyboard-response stimulus, and tells you the x- and y-coordinate boundaries for the target (image) rectangle. By comparing each of the x/y locations from the <code>webgazer_data</code> locations array with the target boundaries in <code>webgazer_targets</code>, you can determine if/when the estimated gaze location was inside the target area.</p>
|
|
<div class="highlight"><pre><span></span><code><span class="p">{</span>
|
|
<span class="s2">"rt"</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
|
|
<span class="s2">"stimulus"</span><span class="o">:</span> <span class="s2">"img/blue.png"</span><span class="p">,</span>
|
|
<span class="s2">"response"</span><span class="o">:</span> <span class="kc">null</span><span class="p">,</span>
|
|
<span class="s2">"trial_type"</span><span class="o">:</span> <span class="s2">"image-keyboard-response"</span><span class="p">,</span>
|
|
<span class="s2">"trial_index"</span><span class="o">:</span> <span class="mf">4</span><span class="p">,</span>
|
|
<span class="s2">"time_elapsed"</span><span class="o">:</span> <span class="mf">30701</span><span class="p">,</span>
|
|
<span class="s2">"internal_node_id"</span><span class="o">:</span> <span class="s2">"0.0-4.0"</span><span class="p">,</span>
|
|
<span class="s2">"webgazer_data"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">1065</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">437</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">39</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">943</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">377</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">79</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">835</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">332</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">110</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">731</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">299</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">146</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">660</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">271</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">189</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">606</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">251</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">238</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">582</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">213</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">288</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">551</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">200</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">335</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">538</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">183</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">394</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">514</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">177</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">436</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">500</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">171</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">493</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">525</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">178</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">542</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">537</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">182</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">592</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">543</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">178</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">633</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">547</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">177</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">691</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">558</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">174</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">739</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">574</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">183</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">789</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">577</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">197</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">838</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">584</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">214</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">889</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">603</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">218</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">937</span><span class="p">},</span>
|
|
<span class="p">{</span> <span class="s2">"x"</span><span class="o">:</span> <span class="mf">606</span><span class="p">,</span> <span class="s2">"y"</span><span class="o">:</span> <span class="mf">221</span><span class="p">,</span> <span class="s2">"t"</span><span class="o">:</span> <span class="mf">987</span><span class="p">}</span>
|
|
<span class="p">],</span>
|
|
<span class="s2">"webgazer_targets"</span><span class="o">:</span> <span class="p">[</span>
|
|
<span class="s2">"#jspsych-image-keyboard-response-stimulus"</span><span class="o">:</span> <span class="p">{</span>
|
|
<span class="s2">"x"</span><span class="o">:</span> <span class="mf">490</span><span class="p">,</span>
|
|
<span class="s2">"y"</span><span class="o">:</span> <span class="mf">135</span><span class="p">,</span>
|
|
<span class="s2">"height"</span><span class="o">:</span> <span class="mf">300</span><span class="p">,</span>
|
|
<span class="s2">"width"</span><span class="o">:</span> <span class="mf">300</span><span class="p">,</span>
|
|
<span class="s2">"top"</span><span class="o">:</span> <span class="mf">135</span><span class="p">,</span>
|
|
<span class="s2">"bottom"</span><span class="o">:</span> <span class="mf">435</span><span class="p">,</span>
|
|
<span class="s2">"left"</span><span class="o">:</span> <span class="mf">490</span><span class="p">,</span>
|
|
<span class="s2">"right"</span><span class="o">:</span> <span class="mf">790</span>
|
|
<span class="p">}</span>
|
|
<span class="p">]</span>
|
|
<span class="p">}</span>
|
|
</code></pre></div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</article>
|
|
</div>
|
|
</div>
|
|
|
|
</main>
|
|
|
|
|
|
<footer class="md-footer">
|
|
|
|
<nav class="md-footer__inner md-grid" aria-label="Footer">
|
|
|
|
|
|
<a href="../fullscreen/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Fullscreen Experiments" rel="prev">
|
|
<div class="md-footer__button md-icon">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z"/></svg>
|
|
</div>
|
|
<div class="md-footer__title">
|
|
<div class="md-ellipsis">
|
|
<span class="md-footer__direction">
|
|
Previous
|
|
</span>
|
|
Fullscreen Experiments
|
|
</div>
|
|
</div>
|
|
</a>
|
|
|
|
|
|
|
|
<a href="../exclude-browser/" class="md-footer__link md-footer__link--next" aria-label="Next: Exclude Participants Based on Browser Features" rel="next">
|
|
<div class="md-footer__title">
|
|
<div class="md-ellipsis">
|
|
<span class="md-footer__direction">
|
|
Next
|
|
</span>
|
|
Exclude Participants Based on Browser Features
|
|
</div>
|
|
</div>
|
|
<div class="md-footer__button md-icon">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z"/></svg>
|
|
</div>
|
|
</a>
|
|
|
|
</nav>
|
|
|
|
<div class="md-footer-meta md-typeset">
|
|
<div class="md-footer-meta__inner md-grid">
|
|
<div class="md-footer-copyright">
|
|
|
|
<div class="md-footer-copyright__highlight">
|
|
Copyright © 2012-2021 Josh de Leeuw
|
|
</div>
|
|
|
|
Made with
|
|
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
|
Material for MkDocs
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<div class="md-footer-social">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://github.com/jspsych" target="_blank" rel="noopener" title="github.com" class="md-footer-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<a href="https://twitter.com/joshdeleeuw" target="_blank" rel="noopener" title="twitter.com" class="md-footer-social__link">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
</div>
|
|
<div class="md-dialog" data-md-component="dialog">
|
|
<div class="md-dialog__inner md-typeset"></div>
|
|
</div>
|
|
<script id="__config" type="application/json">{"base": "../..", "features": [], "translations": {"clipboard.copy": "Copy to clipboard", "clipboard.copied": "Copied to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.placeholder": "Type to start searching", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.term.missing": "Missing", "select.version.title": "Select version"}, "search": "../../assets/javascripts/workers/search.709b4209.min.js", "version": {"provider": "mike"}}</script>
|
|
|
|
|
|
<script src="../../assets/javascripts/bundle.febc23d1.min.js"></script>
|
|
|
|
|
|
</body>
|
|
</html> |