|
@ -1,13 +1,10 @@ |
|
|
import React, { useEffect } from "react"; |
|
|
import React, { useEffect } from "react"; |
|
|
import h337 from "heatmap.js"; |
|
|
import h337 from "heatmap.js"; |
|
|
import { MOUSE_MODE, HEATMAP_MAX } from "../../core/Constants"; |
|
|
|
|
|
|
|
|
import { HEATMAP_MAX } from "../../core/Constants"; |
|
|
|
|
|
|
|
|
var stopInput = false; |
|
|
var stopInput = false; |
|
|
|
|
|
|
|
|
var heatmapInstance = h337.create({ |
|
|
|
|
|
container: document.body, |
|
|
|
|
|
radius: 20, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
var heatmapInstance; |
|
|
|
|
|
|
|
|
const visualiseMouseData = (mouseData) => { |
|
|
const visualiseMouseData = (mouseData) => { |
|
|
mouseData.max = mouseData.data.length + 1; |
|
|
mouseData.max = mouseData.data.length + 1; |
|
@ -16,53 +13,154 @@ const visualiseMouseData = (mouseData) => { |
|
|
stopInput = true; |
|
|
stopInput = true; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var ongoingTouches = []; |
|
|
|
|
|
|
|
|
export function StudySite(props) { |
|
|
export function StudySite(props) { |
|
|
useEffect(() => { |
|
|
useEffect(() => { |
|
|
window.visualiseMouseData = visualiseMouseData; |
|
|
window.visualiseMouseData = visualiseMouseData; |
|
|
heatmapInstance.setDataMax(HEATMAP_MAX); |
|
|
|
|
|
var addData; |
|
|
|
|
|
|
|
|
|
|
|
if (MOUSE_MODE) { |
|
|
|
|
|
const mouseDataFunc = function (ev) { |
|
|
|
|
|
if (!stopInput) { |
|
|
|
|
|
|
|
|
var body = document.getElementById("root"); |
|
|
|
|
|
var html = document.documentElement; |
|
|
|
|
|
|
|
|
|
|
|
var height = Math.max( |
|
|
|
|
|
body.scrollHeight, |
|
|
|
|
|
body.offsetHeight, |
|
|
|
|
|
body.clientHeight, |
|
|
|
|
|
html.clientHeight, |
|
|
|
|
|
html.scrollHeight, |
|
|
|
|
|
html.offsetHeight |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
document.body.style.height = height; |
|
|
|
|
|
document.documentElement.style.height = height; |
|
|
|
|
|
|
|
|
|
|
|
if (heatmapInstance === undefined) { |
|
|
|
|
|
heatmapInstance = h337.create({ |
|
|
|
|
|
container: document.getElementById("studySiteContainer"), |
|
|
|
|
|
radius: 40, |
|
|
|
|
|
}); |
|
|
|
|
|
heatmapInstance.setDataMax(HEATMAP_MAX); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
document.addEventListener("mousemove", function (event) { |
|
|
|
|
|
var x = event.pageX; |
|
|
|
|
|
var y = event.pageY; |
|
|
|
|
|
|
|
|
|
|
|
// Add data to the heatmap |
|
|
|
|
|
heatmapInstance.addData({ x: x, y: y, value: 1 }); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Function to capture clicks |
|
|
|
|
|
document.addEventListener("click", function (event) { |
|
|
|
|
|
var x = event.pageX; |
|
|
|
|
|
var y = event.pageY; |
|
|
|
|
|
|
|
|
|
|
|
// Add more value for clicks |
|
|
|
|
|
heatmapInstance.addData({ x: x, y: y, value: 5 }); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Function to update heatmap container size on resize |
|
|
|
|
|
function updateHeatmapSize() { |
|
|
|
|
|
var container = document.getElementById("heatmapOverlay"); |
|
|
|
|
|
container.style.width = document.body.scrollWidth + "px"; |
|
|
|
|
|
container.style.height = document.body.scrollHeight + "px"; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const handleStart = (evt) => { |
|
|
|
|
|
const touches = evt.changedTouches; |
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < touches.length; i++) { |
|
|
|
|
|
ongoingTouches.push(copyTouch(touches[i])); |
|
|
|
|
|
heatmapInstance.addData({ |
|
|
|
|
|
x: touches[i].pageX, |
|
|
|
|
|
y: touches[i].pageY, |
|
|
|
|
|
value: 5, |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleMove = (evt) => { |
|
|
|
|
|
const touches = evt.changedTouches; |
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < touches.length; i++) { |
|
|
|
|
|
const idx = ongoingTouchIndexById(touches[i].identifier); |
|
|
|
|
|
|
|
|
|
|
|
if (idx >= 0) { |
|
|
heatmapInstance.addData({ |
|
|
heatmapInstance.addData({ |
|
|
x: ev.x, |
|
|
|
|
|
y: ev.y, |
|
|
|
|
|
value: 1, |
|
|
|
|
|
|
|
|
x: touches[i].pageX, |
|
|
|
|
|
y: touches[i].pageY, |
|
|
|
|
|
value: 5, |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
ongoingTouches.splice(idx, 1, copyTouch(touches[i])); // swap in the new touch record |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("can't figure out which touch to continue"); |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleEnd = (evt) => { |
|
|
|
|
|
const touches = evt.changedTouches; |
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < touches.length; i++) { |
|
|
|
|
|
let idx = ongoingTouchIndexById(touches[i].identifier); |
|
|
|
|
|
|
|
|
addData = mouseDataFunc; |
|
|
|
|
|
} else { |
|
|
|
|
|
const touchDataFunc = function (ev) { |
|
|
|
|
|
if (!stopInput) { |
|
|
|
|
|
|
|
|
if (idx >= 0) { |
|
|
heatmapInstance.addData({ |
|
|
heatmapInstance.addData({ |
|
|
x: ev.layerX, |
|
|
|
|
|
y: ev.layerY, |
|
|
|
|
|
value: 1, |
|
|
|
|
|
|
|
|
x: touches[i].pageX, |
|
|
|
|
|
y: touches[i].pageY, |
|
|
|
|
|
value: 5, |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
ongoingTouches.splice(idx, 1); // remove it; we're done |
|
|
|
|
|
} else { |
|
|
|
|
|
console.log("can't figure out which touch to end"); |
|
|
} |
|
|
} |
|
|
}; |
|
|
|
|
|
addData = touchDataFunc; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
if (MOUSE_MODE) { |
|
|
|
|
|
document.body.addEventListener("mousemove", addData, false); |
|
|
|
|
|
} else { |
|
|
|
|
|
document.body.addEventListener("touchmove", addData, false); |
|
|
|
|
|
document.body.addEventListener("touchstart", addData, false); |
|
|
|
|
|
document.body.addEventListener("touchend", addData, false); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
const ongoingTouchIndexById = (idToFind) => { |
|
|
|
|
|
for (let i = 0; i < ongoingTouches.length; i++) { |
|
|
|
|
|
const id = ongoingTouches[i].identifier; |
|
|
|
|
|
|
|
|
|
|
|
if (id === idToFind) { |
|
|
|
|
|
return i; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return -1; // not found |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const copyTouch = ({ identifier, pageX, pageY }) => { |
|
|
|
|
|
return { identifier, pageX, pageY }; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleCancel = (evt) => { |
|
|
|
|
|
const touches = evt.changedTouches; |
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < touches.length; i++) { |
|
|
|
|
|
let idx = ongoingTouchIndexById(touches[i].identifier); |
|
|
|
|
|
ongoingTouches.splice(idx, 1); // remove it; we're done |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
document.body.ontouchstart = handleStart; |
|
|
|
|
|
document.body.ontouchend = handleEnd; |
|
|
|
|
|
document.body.ontouchcancel = handleCancel; |
|
|
|
|
|
document.body.ontouchmove = handleMove; |
|
|
|
|
|
|
|
|
|
|
|
// Update the size initially and on resize |
|
|
|
|
|
updateHeatmapSize(); |
|
|
|
|
|
window.addEventListener("resize", updateHeatmapSize); |
|
|
|
|
|
window.addEventListener("scroll", updateHeatmapSize); |
|
|
|
|
|
|
|
|
return () => { |
|
|
return () => { |
|
|
delete window.visualiseMouseData; |
|
|
delete window.visualiseMouseData; |
|
|
}; |
|
|
}; |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
return <>{props.children}</>; |
|
|
|
|
|
|
|
|
return <div id="studySiteContainer">{props.children}</div>; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
export function getHeatmapData() { |
|
|
export function getHeatmapData() { |
|
|
return heatmapInstance.getData(); |
|
|
|
|
|
|
|
|
return (heatmapInstance !== undefined) ? heatmapInstance.getData() : {}; |
|
|
} |
|
|
} |