Skip to content

Commit

Permalink
Merge pull request #292 from ct-martin/heatmap
Browse files Browse the repository at this point in the history
Basic heatmap example
  • Loading branch information
jeffhuang authored Mar 28, 2023
2 parents 0e84b63 + 7a14051 commit 4dc5432
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 13 deletions.
38 changes: 38 additions & 0 deletions www/heatmap.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<title>Webgazer.js + heatmap.js demo</title>
<style>
/* Make sure everything in body can go to the edge of the page */
/* Particularly, Chrome's default styles have an 8px margin for the body */
html, body {
margin: 0;
padding: 0;
}
/* Make body take up entire page */
body, #content {
width: 100vw;
height: 100vh;
}
/* Make the image autoscale to the page */
#content {
object-fit: contain;
}
/* Put the heatmap on top of the image */
#heatmapContainer {
/* The heatmap will set its own size to the window's via JS */
z-index: 10;
position: fixed !important;
top: 0;
left: 0;
}
</style>
</head>
<body>
<img id="content" src="media/example/starrynight.jpg" />
<div id="heatmapContainer"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/localforage/1.8.1/localforage.js"></script>
<script src="./webgazer.js"></script>
<script src="./node_modules/heatmap.js/build/heatmap.min.js"></script>
<script src="js/heatmap-demo.js"></script>
</body>
102 changes: 102 additions & 0 deletions www/js/heatmap-demo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Set to true if you want to save the data even if you reload the page.
window.saveDataAcrossSessions = false;

// heatmap configuration
const config = {
radius: 25,
maxOpacity: .5,
minOpacity: 0,
blur: .75
};

// Global variables
let heatmapInstance;

window.addEventListener('load', async function() {
// Init webgazer
if (!window.saveDataAcrossSessions) {
var localstorageDataLabel = 'webgazerGlobalData';
localforage.setItem(localstorageDataLabel, null);
var localstorageSettingsLabel = 'webgazerGlobalSettings';
localforage.setItem(localstorageSettingsLabel, null);
}
const webgazerInstance = await webgazer.setRegression('ridge') /* currently must set regression and tracker */
.setTracker('TFFacemesh')
.begin();

// Turn off video
webgazerInstance.showVideoPreview(false) /* shows all video previews */
.showPredictionPoints(false); /* shows a square every 100 milliseconds where current prediction is */

// Enable smoothing
webgazerInstance.applyKalmanFilter(true); // Kalman Filter defaults to on.

// Set up heatmap parts
setupHeatmap();
webgazer.setGazeListener( eyeListener );
});

window.addEventListener('beforeunload', function() {
if (window.saveDataAcrossSessions) {
webgazer.end();
} else {
localforage.clear();
}
});

// Trimmed down version of webgazer's click listener since the built-in one isn't exported
// Needed so we can have just the click listener without the move listener
// (The move listener was creating a lot of drift)
async function clickListener(event) {
webgazer.recordScreenPosition(event.clientX, event.clientY, 'click'); // eventType[0] === 'click'
}

function setupHeatmap() {
// Don't use mousemove listener
webgazer.removeMouseEventListeners();
document.addEventListener('click', clickListener);

// Get the window size
let height = window.innerHeight;
let width = window.innerWidth;

// Set up the container
let container = document.getElementById('heatmapContainer');
container.style.height = `${height}px`;
container.style.width = `${width}px`;
config.container = container;

// create heatmap
heatmapInstance = h337.create(config);
}

// Heatmap buffer
let lastTime;
let lastGaze;

async function eyeListener(data, clock) {
// data is the gaze data, clock is the time since webgazer.begin()

// Init if lastTime not set
if(!lastTime) {
lastTime = clock;
}

// In this we want to track how long a point was being looked at,
// so we need to buffer where the gaze moves to and then on next move
// we calculate how long the gaze stayed there.
if(!!lastGaze) {
if(!!lastGaze.x && !!lastGaze.y) {
let duration = clock-lastTime;
let point = {
x: Math.floor(lastGaze.x),
y: Math.floor(lastGaze.y),
value: duration
}
heatmapInstance.addData(point);
}
}

lastGaze = data;
lastTime = clock;
}
Binary file added www/media/example/starrynight.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 6 additions & 13 deletions www/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"bootstrap": "^5.2.3",
"browser-sync": "^2.26.12",
"d3": "^5.16.0",
"heatmap.js": "^2.0.5",
"sweetalert": "^2.1.2"
},
"overrides": {
Expand Down

0 comments on commit 4dc5432

Please sign in to comment.