如何解决基于heatmap.js的响应式UI交互热图偏移问题
问题背景
我已经编写自动化脚本追踪用户与UI的交互行为,会记录mousemove与click事件的触发位置。如果不考虑响应式适配要求,当前工作已经可以直接交付,但我希望实现适配效果完美的响应式热图。目前正处于概念验证(POC)阶段,核心功能主要依赖heatmap.js实现。

现有实现与问题
当前我通过event.pageX与event.pageY存储事件的绝对触发位置,同时记录交互发生时的window.innerWidth与window.innerHeight,试图推导可根据不同设备尺寸调整位置偏移的计算函数。但实际效果存在缺陷:静态视口下热图可正常对齐UI(如上述示例图),但视口缩窄后热图会出现明显错位:

不再赘述细节排查过程,以下为核心示例代码:
// 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...
当setupHeatMaps函数中绑定的pages元素宽度发生变化时,热图数据的展示会出现严重错位。我已花费大量时间梳理该问题原因,但暂未找到合理的解决方案。
备选思路
我也曾考虑是否可以直接将页面截图与热图叠加存储,这样无需处理热图的响应式适配问题,但该方案需要解决其他衍生问题:比如数据版本管理,若用户使用手机访问页面,需要将会话数据与之前笔记本、桌面端的会话数据分开存储。
问询
目前我暂未明确最优的实现方案,请问是否有开发者遇到过同类问题?是否有巧妙的解法可以解决该问题?
补充说明:因整体解决方案涉及的代码量极大,无法全部分享。当前为概念验证(POC)阶段,通常我会将background与热图容器div元素的渲染逻辑交由底层框架处理,而非直接通过JS操作DOM,特此说明。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

