The Problem
I've encountered a slight problem where I've written some code where I've automated a script to track the users interactions with a UI, including mousemove
& click
events. If I didn't have to worry about making it responsive, then I could probably call it a day & ship the work that I've done already, however my brain is seeking some wizardry knowledge, I'm struggling to make it super responsive. Here's just a quick example of the kinda thing that I'm working on, it's nothing genius, if anything I it's mostly heatmap.js that's doing the heavy lifting. Currently I'm just seeing if I can do this as a proof of concept more than anything else...
The Code
So currently, I'm tracking the event.pageX
& event.pageY
values to store exactly where an event took place, I'm also storing the window.innerWidth
& window.innerHeight
values to try & work out some function that would allow me to offset the positions based on the size(s) of other devices.
E.g. If you look at the sample image above, that's perfect for a static page, but if I were to say make the page a little more narrow, you can see here that it's doesn't line up with the image above:
Anyway, without blabbering on too much, here's some sample code:
// A lot of other code...
var setupHeatMaps = function (pages, heatMaps) {
pages.forEach(function (page) {
page.addEventListener("click", function (event) {
heatMaps.push({ x: event.pageX, y: event.pageY, value: 10000 });
onStateChange();
});
// Don't collect ALL mouse movements, that'd be crazy, so collect
// every 1/10 mouse movements.
var counter = 0;
page.addEventListener("mousemove", function (event) {
if (counter === 10) {
heatMaps.push({ x: event.pageX, y: event.pageY, value: 20 });
onStateChange();
counter = 0;
} else {
counter ++;
}
});
});
};
// A lot of other code...
// Curried function so that it can be passed around without exposing the state...
var renderHeatMaps = function (heatMaps) {
return function () {
var max = heatMaps.length;
var points = heatMaps;
var parent = getParentElement();
var styleObj = window.getComputedStyle(parent);
var div = document.createElement("div");
var body = document.querySelector("body");
var background = document.createElement("div");
// This element needs to sit in front of the
// background element, hence the higher z-index value.
div.style.position = "absolute";
div.style.zIndex = 9;
div.style.left = "0px";
div.style.top = "-80px";
div.style.width = "100vw";
// Even though this element will sit behind the element
// that's created above, we will still want this element to
// sit in front of 99% of the content that's on the page.
background.style.position = "fixed";
background.style.top = "0px";
background.style.left = "0px";
background.style.height = "100vh";
background.style.width = "100vw";
background.style.zIndex = 5;
background.style.backgroundColor = "rgba(255, 255, 255, 0.35)";
background.setAttribute("id", "quote-customer-heat-map-background");
var heightInPx = styleObj.getPropertyValue("height");
var rawHeight = parseInt(heightInPx.replace("px", ""));
var newHeight = parseInt((rawHeight + 80));
div.style.height = newHeight + "px";
div.setAttribute("id", "quote-customer-heat-map-foreground");
body.style.paddingBottom = "0px";
body.appendChild(background);
body.appendChild(div);
var heatMap = h337.create({
container: div,
radius: 45
});
heatMap.setData({ max: max, data: points });
};
};
// A lot of other code...
As the pages
elements that you can see being used in setupHeatMaps
changes in width, viewing this data gets offset quite badly. I'll be honest, I've spent a lot of time yesterday thinking about this issue & I've still not thought of anything that seems reasonable.
Alternatively
I have wondered if I should somehow just store the page as an image, with the heatmap overplayed, that way I wouldn't really have to worry about the heatmap being responsive. But then I need to figure out some other things... E.g. Versioning this data, so in the event that a user views a page on their phone, it'll stored that data separately to data that was collected from a previous session where they were on a laptop or on a desktop device.
Conclusion
I'll be honest, I'm not entirely sure what the best course of action is, have any of you guys encountered anything like this before? Have you guys thought of something genius that solves an issue like this?
P.S. I would share a lot more code, however there's an immense amount of code that goes into this overall solution, so I kinda can't share all of it, I'm pretty sure the guys at Stackoverflow would hate me for that! 😅 - You can also tell that I'm doing this as a POC because normally I'd just offload the rendering of the background
element & the div
element to the underlying framework rather than do it programatically like this, keep that in mind, this is just a POC.
from Responsive Heatmaps
No comments:
Post a Comment