欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > 前端埋点系统之如何用heatmap.js画网页热力图

前端埋点系统之如何用heatmap.js画网页热力图

2025/4/19 17:07:02 来源:https://blog.csdn.net/webfunny2020/article/details/143468329  浏览:    关键词:前端埋点系统之如何用heatmap.js画网页热力图

Hello,大家好。在当今数字化时代,理解用户行为成为了企业成功的关键之一。随着互联网的发展,用户与网站、应用和产品的互动变得愈发复杂而多样化。在这样的背景下,埋点系统成为了洞察用户行为的重要工具之一。而其中的热力图分析,则更加直观的帮助我们分析用户的喜好。

之前我们介绍了什么是热力图,以及它如何成为理解用户行为的有力工具。今天我们从技术的角度来看,如何实现热力图效果呢?

热力图是埋点系统必不可少的一项能力,可以来看看Webfunny一体化埋点系统的效果

一、有哪些免费工具可以实现热力图效果

热力图主要的实现方式,还是利用目前现有的开源工具,如:百度的echarts、阿里系的G2、还有就是我们今天要说的heatmap.js。

当然,你如果有兴趣和精力,可以自己手搓一个,原理也不是特别复杂,关于热力图的实现原理:

一般可大致归纳为以下几个步骤:

  1. 为每个数据点设置一个从中心向外灰度渐变的圆;

  2. 利用灰度可以叠加的原理,计算每个像素点数据交叉叠加得到的灰度值;

  3. 根据每个像素计算得到的灰度值,在一条彩色色带中进行颜色映射,最后对图像进行着色,得到热力图。

百度echarts的热力图效果

在这里插入图片描述

阿里系的G2热力图效果

在这里插入图片描述

heatmap.js热力图效果

在这里插入图片描述

根据效果来看,其中G2和heatmap.js的热力图效果都比较符合我们的使用场景,heatmap.js已经处理好颜色效果了,所以最后选择了heatmap.js。

二、如何采集网页上的热力数据

热力图在我们的印象中,主要的使用场景是在地图上,比如哪个地方温度,就会呈现红色,哪个地方的温度低就会呈现蓝色。而我们今天要做的是,采集网页上的热力图,主要包含三个指标的数据。

网页上又没有温度,哪来的热力值呢,他们分别是:鼠标点击量、鼠标停留时长、页面元素曝光时长

1. 点击热力数据
点击量热力图和好理解,点击的越多,热力值则越高。采集方式是通过监听全局点击事件,需要采集的几个主要的指标有:

页面地址:这个是用来确定是哪个页面的;

页面宽度/高度:这个是用来确定页面尺寸的;

鼠标点击位置(x坐标,y坐标):这个是用来锁定页面坐标,计算热力值的;

/*** 启动点击事件监听*/
export function startClickRecord() {window.addEventListener('click',function(e){console.log('触发点击事件!', e)if (!e) return/** 检查定时器是否开启 */if (store.timerStatus === 'off') {console.log('定时器已结束,触发鼠标点击,则重新开启')store.timerStatus = 'on';startGlobalTimer()}try {const scrollWidth = (document.body ? document.body.scrollWidth : 0) || window.innerWidthconst weTitle = document.titleconst wePath = Utils.b64Code(Utils.getPath())const weFullPath = Utils.b64Code(Utils.getPath('full'))const weScrollWidth = scrollWidth - scrollWidth % 20const weScrollHeigh = (document.body ? document.body.scrollHeight : 0) || window.innerHeightconst weXPath = Utils.getXPath(e)const wePageX = e.pageXconst wePageY = e.pageY// const weScrollX = window.scrollX// const weScrollY = window.scrollYconst weRatio = parseInt(window.devicePixelRatio)// 上报点击数据const data = {weTitle, wePath, weScrollWidth, weScrollHeigh, weXPath, weFullPath, wePageX, wePageY, weRatio}webfunnyGlobal.webfunnyEvent('Webfunny-Replace-HeatMapClickPointId').trackEvent(data);} catch(e) {console.error('click error', e)}}, true);
}

2. 鼠标停留时长热力图
点击量是直接反映用户达成的目标,鼠标停留时间则是反应了用户的兴趣之所在,也很重要。停留和点击的热力图很相似,只是停留时长的热力图数据会更密集一些。

鼠标停留时间的采集方式跟点击类似,通过监听mousemove事件进行采集,需要采集的几个主要的指标有:

页面地址:这个是用来确定是哪个页面的;

页面宽度/高度:这个是用来确定页面尺寸的;

鼠标点击位置(x坐标,y坐标):这个是用来锁定页面坐标,计算热力值的;

停留时间:这是一个关键性指标,这个值的上限是一个不确定的,但是它的上限对热力值的影响很大。

例如:如何设置很高,就会影响热力的准确性,用户鼠标放在哪里不动,那个点的热力值就会很高,其实他只有一个用户,并不能反馈出有价值的数据;如果设置很低,又无法反馈用户真是的停留时长了,所以这里的做成动态配置的最好。

建议:用户量小的应用,这个上限值设置低一些, 如:1000ms,因为个别用户会造成较大影响;用户量大的应用,设置稍微偏高些,2000ms,大量的用户会让拉平整体的数据,让数据趋于准确。

/*** 启动鼠标停留事件监听*/
export function startMousemoveRecord() {console.log('全埋点,鼠标停留时长,启动')let timerwindow.addEventListener('mousemove',function(e){if (!e) returnif (timer) {clearTimeout(timer)}/** 检查定时器是否开启 */if (store.timerStatus === 'off') {console.log('定时器已结束,触发鼠标移动,则重新开启')store.timerStatus = 'on';startGlobalTimer()}timer = setTimeout(() => {try {const weTitle = document.titleconst scrollWidth = (document.body ? document.body.scrollWidth : 0) || window.innerWidthconst wePath = Utils.b64Code(Utils.getPath())const weFullPath = Utils.b64Code(Utils.getPath('full'))const weScrollWidth = scrollWidth - scrollWidth % 20const weScrollHeigh = (document.body ? document.body.scrollHeight : 0) || window.innerHeightconst weXPath = Utils.getXPath(e)const wePageX = e.pageXconst wePageY = e.pageY// const weScrollX = window.scrollX// const weScrollY = window.scrollYconst weRatio = parseInt(window.devicePixelRatio)const mousemoveInfo = {weTitle, wePath, weScrollWidth, weScrollHeigh, weXPath, weFullPath, wePageX, wePageY, weRatio}// 鼠标移动停留生效console.log('鼠标移动停留生效:', store.mouseStayInfo)if (!store.mouseStayInfo) {// 如果没有记录信息,直接存入内存中store.mouseStayInfo = { ...mousemoveInfo, startTime: new Date().getTime() }} else {// 如果有记录信息,就需要将之前的停留信息放进任务队列,并重新记录当前有效的停留const nowTime = new Date().getTime()const { startTime = 0 } = store.mouseStayInfo || {}let timeDiff = nowTime - startTimeconsole.log('鼠标距离上次时间差:', timeDiff, wePageX, wePageY)if (timeDiff > 150) {// 如果停留时间超过上限, 则默认为上限时间timeDiff = timeDiff > COMMON_FIELD.MOUSE_STAY_LIMIT ? COMMON_FIELD.MOUSE_STAY_LIMIT : timeDiffconst tempMousemoveInfo = { ...mousemoveInfo, stayTime: timeDiff }// TaskQueue.addTask(config.trackUrl, tempMousemoveInfo)// 上报鼠标移动数据console.log('即将执行上报', tempMousemoveInfo)webfunnyGlobal.webfunnyEvent('Webfunny-Replace-HeatMapStopPointId').trackEvent(tempMousemoveInfo);store.mouseStayInfo = { ...mousemoveInfo, startTime: nowTime }}}} catch(e) {console.error('mousemove error: ', e)}}, 200)}, true);// 鼠标离开浏览器后,需要清理历史数据,延迟1s,防止window.addEventListener('mouseout', function(e){var tagName = e.target.tagName ? e.target.tagName.toLowerCase() : ''if (tagName === 'html') {setTimeout(function() {store.mouseStayInfo = ''console.log('鼠标移出了浏览器, 清理鼠标停留数据', store.mouseStayInfo)}, 1000)}}, true)
}

三、如何将热力图覆盖到网页上呢

热力数据采集到了,怎么才能将它们正确的放到网页上呢。

其实也简单,上层是heatmap.js生成的热力效果图;下层是iframe,显示的是网页内容,这样热力图效果就呈现出来了。

在这里插入图片描述

需要注意的是:网页会滚动,宽度也不同,鼠标停留和点击的位置需要取相对位置,而不是绝对位置

四、heatmap.js生成热力图代码

生成heatmap对象,并将热力值数据一个个填充进去就可以了。

heatmap的配置项有很多,下方是我试验出来比较简单的配置项。

安装依赖:npm install heatmap.js --save

import h337 from “heatmap.js”

// 查找元素
const heatEle = document.getElementById(this.state.heatId)
heatmapInstance = h337.create({
container: heatEle,
// radius: 30,
// maxOpacity: 0.7

      radius: 20, // 点的半径// maxOpacity: 0.8, // 最大不透明度// minOpacity: 0.2, // 最小不透明度blur: 0.75, // 模糊半径useLocalExtrema: true, // 是否使用局部极值});this.props.dataList.forEach((item) => {heatmapInstance.addData({x: item.x,y: item.y,value: item.value * 100});})

五、热力图细节优化

heatmap的热力效果虽然不错,但是我并未在文档中找到能提示热力值的API,这就有点尴尬了,因为热力图效果虽然好,但是没有热力值提示,总会让人觉得缺点什么

没办法,只有手动加一个了;虽然heatmap没有提供tip提示,但是却提供了获取热力值的API,这下就简单多了,添加鼠标移动事件,在鼠标位置上方添加div显示热力值,不要忘记延时显示和添加防抖哦

在这里插入图片描述

代码如下:

let mousemoveTimer = 0heatEle.addEventListener("mousemove", (e) => {const { offsetX, offsetY } = econst heatTipCon = heatmapInstance.getValueAt({ x: offsetX, y: offsetY })if (mousemoveTimer) {clearTimeout(mousemoveTimer)mousemoveTimer = setTimeout(() => {this.setState({heatTipCon: heatTipCon / 100, heatTipX: offsetX, heatTipY: offsetY - 20})}, 300)} else {mousemoveTimer = setTimeout(() => {this.setState({heatTipCon: heatTipCon / 100, heatTipX: offsetX, heatTipY: offsetY - 20})}, 300)}})

以上是如何利用heatmap实现热力图效果介绍,感兴趣的同学可以直接访问webfunny前端监控和前端埋点系统
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词