您现在的位置是:首页>博客详情

基于heatmap.js html2canvas.js生成页面点击热力图

FreshMan2022年03月22日 11:29点击热力图;滚动记录;网页截图1194

简介在自然界之中,蛇的眼睛有夜视功能,即便是茫茫黑夜,它也能轻而易举的找到猎物,这是因为任何物体都会辐射热红外,且辐射的高低和温度成正比,由于生命体的体温会明显高于周围环境的温度,所以在蛇眼面前便无处遁形。热红外成像被广泛应用于军事领域,士兵带上能识别热红外的眼镜后能轻而易举的发现藏匿的敌人。

    生成页面热力图是前端需要在大数据环境下进行展示的需求,比如需要看看页面哪些位置用户点击量比较多,哪些位置是用户比较关注的,利用数据分析能够更好的优化用户体验,提升页面转化率。

    经过分析,我认为主要有两点需要注意:

    1、一般像APP页面或者网页,都是拥有很大的流量,所以点击次数肯定都是百万级的;
    2、热力值肯定要根据点击次数做出对应的调整;
    所以,问题的关键就是怎么生成对应坐标的热力值?一般的思路是,设定好每次点击的热力值,然后在当重复点击同一坐标时进行累加;错误的思路肯定是不行了,所以上面的pass!为啥不行就留给读者自己探索了~
    现在来说下我的思路:
    1)首先既然数据都是百万级的所以肯定不能给每一个坐标都进行处理,因此我们要限定要渲染的坐标,以手机移动端为例,我先限定要生成热力图的部分分成50*200=10000个小格子,然后将每个小格子的中心点作为我将要渲染的坐标,这样不管来多少条数据,我最多只需要渲染10000个坐标即可!(注意:这样就说明用户每次点击的坐标如果在某个小格子的范围内都是会被替换成小格子中心点坐标的)
    2)那就是热力值的计算了:
        (1)首先我设定最大热力值为1000(这个随意,推荐选个好计算的值);
        (2)然后所有被点击坐标的点击次数设为:index。其中肯定有最大值,设为:clickMax;

        (3)所以热力值计算公式就出来了:

            hotNum = index/clickMax*1000;

            这样就可以适应到不同点击次数下的热力值了。 有更好的方法,欢迎留言~

    话不多说,开始码代码:
    页面结构及样式

<style>

        body {

            -webkit-user-select: none;

            -moz-user-select: none;

            -ms-user-select: none;

            user-select: none;

        }


        #heatmap {

            border: 1pxsolid#ccc;

            width: 640px;

            height: 383px;

        }


        .legend-area {

            position: absolute;

            bottom: 0;

            right: 0;

            padding: 10px;

            background: white;

            outline: 3pxsolidblack;

            line-height: 1em;

        }


        h4 {

            margin: 0;

            padding: 0;

            margin-bottom: 5px;

        }


        #min {

            float: left;

        }


        #max {

            float: right;

        }


        span {

            font-size: 14px;

            margin: 0;

            padding: 0;

        }


        .tooltip {

            position: absolute;

            left: 0;

            top: 0;

            background: rgba(0, 0, 0, .8);

            color: white;

            font-size: 14px;

            padding: 5px;

            line-height: 18px;

            display: none;

        }


        .demo-wrapper {

            position: relative;

            height: 400px;

            width: 840px;

            background: rgba(0, 0, 0, .03);

            border: 3 px solidblack;

        }


        .heatmap {

            height: 400px;

            width: 840px;

        }

    </style>

<body>

    <buttonid="btn">生成热力图</button>

    <divid="heatmap">

        <imgsrc="./img/fuchouzhe.png" />

    </div>

</body>

    脚本部分:

<scriptsrc="https://code.jquery.com/jquery-3.6.0.min.js"></script>

    <scriptsrc="js/heatmap.js"></script>

    <script>

        window.onload=function () {

            varheatmapBox=document.getElementById("heatmap");

            varwidth=heatmapBox.offsetWidth;

            varheight=heatmapBox.offsetHeight;

            varpoints= [];

            varminWidth=width/50;

            varminHeight=height/200;


            // 遍历出所有的横坐标

            varxList= [];

            varxNum=minWidth/2;

            varxNumConst=minWidth/2;

            for (vari=0; i<50; i++) {

                xList.push(xNum);

                xNum+=minWidth

            }


            // 遍历出所有的纵坐标

            varyList= [];

            varyNum=minHeight/2;

            varyNumConst=minHeight/2;

            for (vari=0; i<200; i++) {

                yList.push(yNum);

                yNum+=minHeight

            }


            // 遍历出所有的小格子坐标

            varxyList= [];

            for (vara=0; a<xList.length; a++) {

                for (varb=0; b<yList.length; b++) {

                    varxyItem= {

                        x: xList[a],

                        y: yList[b]

                    };

                    xyList.push(xyItem)

                }

            }


            varclickPointLIst= []; // 用来存储坐标被点击次数

            // 当图片被点击时,记录所点击坐标的点击次数

            $("#heatmap").on("click", function (e) {

                varpageX=e.pageX;

                varpageY=e.pageY;

                console.log(pageX, pageY);

                varclickXY=isNewXY(pageX, pageY);

                console.log(clickXY);

                if (clickPointLIst.length>0) {

                    varisflag=0;

                    clickPointLIst.forEach(function (item, index) {

                        varx=item.x;

                        vary=item.y;

                        if (x==clickXY.x&&y==clickXY.y) {

                            isflag++;

                            clickPointLIst[index].index=clickPointLIst[index].index+1

                        }

                    });

                    if (isflag==0) {

                        clickPointLIst.push({

                            x: clickXY.x,

                            y: clickXY.y,

                            index: 1

                        })

                    }

                } else {

                    clickPointLIst.push({

                        x: clickXY.x,

                        y: clickXY.y,

                        index: 1

                    })

                }

            });


            // 根据点击点坐标,生成实际应该起作用的坐标

            functionisNewXY(pageX, pageY) {

                varclickXY= {};

                xyList.forEach(function (item, index) {

                    varx1=item.x-xNumConst;

                    vary1=item.y-yNumConst;

                    varx2=item.x+xNumConst;

                    vary2=item.y+yNumConst;

                    if ((pageX>=x1&&pageX<=x2) && (pageY>=y1&&pageY<=y2)) {

                        clickXY= {

                            x: item.x,

                            y: item.y

                        }

                    }

                });

                returnclickXY

            }


            // 计算出坐标应该对应的热力值

            functioncalcHotNum(clickXY, list) {

                varhotNum=0;

                varmax=0;

                varthisIndex=0;

                list.forEach(function (item, index) {

                    max=Math.max(max, item.index);

                    varx=item.x;

                    vary=item.y;

                    if (x==clickXY.x&&y==clickXY.y) {

                        thisIndex=item.index

                    }

                });

                hotNum=thisIndex/max*1000;

                returnhotNum

            }


            // 点击坐标生成热力图

            $("#btn").on("click", function () {

                varmax=0;

                clickPointLIst.forEach(function (item, index) {

                    varhotNum=calcHotNum(item, clickPointLIst);

                    item.value=hotNum

                    max=Math.max(max, hotNum);

                });

                // console.log(clickPointLIst);

                points=JSON.parse(JSON.stringify(clickPointLIst));

                points.forEach(function (item, index) {

                    deleteitem.index;

                    item.x=Math.floor(item.x);

                    item.y=Math.floor(item.y);

                    // 很诡异,在工作的时候不需要取整,

                    // 结果回家写博客的时候,发现居然坐标不能是小数????

                });

                console.log(points);


                // heatmap坐标值不能为小数

                createHotMap(max, points)

            });


            // 热力图生成

            functioncreateHotMap(max, points) {

                varheatmapInstance=h337.create({

                    container: document.querySelector('#heatmap'),

                });

                vardata= {

                    max: max,

                    data: points

                };

                console.log(data)

                heatmapInstance.setData(data)

            };


            //鼠标点击位置

            $("body").click(function (event) {

                varpos=getMousePos(event);

                console.log(pos);

            });


            functiongetMousePos(event) {

                vare=eventwindow.event;

                varscrollX=document.documentElement.scrollLeftdocument.body.scrollLeft;

                varscrollY=document.documentElement.scrollTopdocument.body.scrollTop;

                varx=e.pageXe.clientX+scrollX;

                vary=e.pageYe.clientY+scrollY;

                //alert('x: ' + x + '\ny: ' + y);

                return {

                    'x': x,

                    'y': y

                };

            }

        }

    </script>

    在图片对应区域进行点击:

QQ拼音截图未命名.jpg

    点击生成热力图:

QQ拼音截图未命名1.jpg

    对于需要更多的配置的,如下比如需要生成图例的,鼠标移动到热力区域返回热力值的 。

image.png

    更多内容请查看附件,以及官网:

    http://html2canvas.hertzen.com/

    https://www.patrick-wied.at/static/heatmapjs/

下载地址:

文件名称:HotMap.zip

文件大小:125KB

更新日期:2022/03/22