1. 云栖社区>
  2. PHP教程>
  3. 正文

浅谈Heatmap技术

作者:用户 来源:互联网 时间:2017-12-01 09:38:19

自然界

浅谈Heatmap技术 - 摘要: 本文讲的是浅谈Heatmap技术, 在自然界之中,蛇的眼睛有夜视功能,即便是茫茫黑夜,它也能轻而易举的找到猎物,这是因为任何物体都会辐射热红外,且辐射的高低和温度成正比,由于生命体的体温会明显高于周围环境的温度,所以在蛇眼面前便无处遁形。热红外成像被广泛应用于军事领域,士兵

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

  

浅谈Heatmap技术

 

  热红外成像

  唠叨了半天,听上去似乎有点跑题了,其实不然,对互联网从业者而言,同样需要有火眼金睛,以便识别网友的喜好,此时的衡量标准是点击,点击越多则表示越喜欢,此技术被称作Heatmap,已经有网站提供此类服务,如:clickdensity,clicktale,crazyegg等等,甚至还有类似clickheat项目提供源代码供你直接使用。

  不过最灵活的方案莫过于自己搞定,下面大概说说Heatmap的实现:

  捕捉点击

  当然,这需要Javascript来实现。为了不陷入浏览器兼容的泥潭,我们选择JQuery:


  1. <script>  
  2.  
  3. jQuery(document).ready(function() {  
  4.     $(document).mousedown(function(e) {  
  5.         if (e.clientX >= $(window).width() || e.clientY >= $(window).height()) {  
  6.             return;  
  7.         }  
  8.  
  9.         $.get("/path/to/a/empty/html/file", {  
  10.             page_x       : e.pageX,  
  11.             page_y       : e.pageY,  
  12.             screen_width : screen.width,  
  13.             screen_height: screen.height  
  14.         });  
  15.     });  
  16. });  
  17.  
  18. </script> 

  客户端使用Ajax通过GET方法触发一个空HTML页面,当然,还可以更简单点:


  1. <script>  
  2.  
  3. var image = new Image();  
  4. image.src = "...";  
  5.  
  6. </script> 

  之所以要记录屏幕分辨率是因为有的情况下需要修正点击坐标。比如说,一个居中显示的定宽的页面,其同一个位置在不同分辨率下的坐标是不同的,当渲染图片的时候,坐标需要以一个分辨率为准进行修正。

  另外,如果用户正在拖动滚动条,是不应该记录的。

  分析日志

  客户端使用Ajax通过GET方法触发一个空HTML页面,如此就会在服务端留下日志:


  1. page_x=...&page_y=...&screen_width=...&screen_height=... 

  不同的日志格式,结果会有所不同,这里仅仅以此为例来说明问题,本文采用AWK来解析日志,当然你也可以使用Perl或别的你熟悉的语言:


  1. #!/usr/bin/awk -f  
  2.  
  3. BEGIN {  
  4.     FS="&";  
  5. }  
  6.  
  7. NF == 4 {  
  8.     param["page_x"]        = "0";  
  9.     param["page_y"]        = "0";  
  10.     param["screen_width"]  = "0";  
  11.     param["screen_height"] = "0";  
  12.  
  13.     split($0, query, "&");  
  14.  
  15.     for (key in query) {  
  16.         split(query[key], item, "=");  
  17.         if (item[1] in param) {  
  18.                 param[item[1]] = item[2];  
  19.         }  
  20.     }  
  21.  
  22.     print "page_x:"       , param["page_x"];  
  23.     print "page_y:"       , param["page_y"];  
  24.     print "screen_width:" , param["screen_width"];  
  25.     print "screen_height:", param["screen_height"];  
  26.  
  27.     print "/n";  

  至于数据的持久化,是使用MongoDB或者别的,自己定夺,这里就不多说了。

  渲染图片

  出于演示方便的考虑,我使用了一些随机生成的数据,以Imagick为例,代码如下:


  1. <?php  
  2.  
  3. $coordinates = array();  
  4.  
  5. for ($i = 0; $i < 1000; $i++) {  
  6.     $coordinates[] = array(rand($i, 1000), rand($i, 1000));  
  7. }  
  8.  
  9. $max_repeat = max(  
  10.     array_count_values(  
  11.         array_map(function($v) { return "{$v[0]}x{$v[1]}"; }, $coordinates)  
  12.     )  
  13. );  
  14.  
  15. $opacity = 1 - 1 / $max_repeat;  
  16.  
  17. $heatmap_image = new Imagick();  
  18.  
  19. $heatmap_image->newImage(1000, 1000, new ImagickPixel('white'));  
  20. $heatmap_image->setImageFormat('png');  
  21.  
  22. $plot_image = new Imagick('plot.png');  
  23.  
  24. $iterator = $plot_image->getPixelIterator();  
  25. foreach($iterator as $row) {  
  26.     foreach ($row as $pixel) {  
  27.         $colors = $pixel->getColor();  
  28.         foreach (array('r''g''b'as $channel) {  
  29.             $color = $colors[$channel];  
  30.             if ($color !== 255) {  
  31.                 $colors[$channel] = $color + ((255 - $color) * $opacity);  
  32.             }  
  33.         }  
  34.  
  35.         $pixel->setColor("rgb({$colors['r']},{$colors['g']},{$colors['b']})");  
  36.     }  
  37.  
  38.     $iterator->syncIterator();  
  39. }  
  40.  
  41. $plot_size = $plot_image->getImageGeometry();  
  42.  
  43. foreach ($coordinates as $pair) {  
  44.     $heatmap_image->compositeImage(  
  45.         $plot_image,  
  46.         Imagick::COMPOSITE_MULTIPLY,  
  47.         $pair[0] - $plot_size['width'] / 2,  
  48.         $pair[1] - $plot_size['height'] / 2  
  49.     );  
  50. }  
  51.  
  52. $color_image = new Imagick('clut.png');  
  53.  
  54. $heatmap_image->clutImage($color_image);  
  55.  
  56. $heatmap_image->writeImage('heatmap.png');  
  57.  
  58. ?> 

  代码虽然很多,但并不复杂,其中用到了两个图片,分别是:plot.png和clut.png。实际应用时,有时候点击量会非常大,此时没有必要把所有的点击都渲染出来,而应该采取随机取样的策略,如果采用MongoDB持久化的话,可以参考:The Random Attribute。

  备注:代码参考image-tempest。

  最终展示

  形象一点来说,其实就是通过CSS+Javascript把生成的图片盖在网页上,并调节图片透明度来达到合二为一的效果,篇幅所限,具体代码留给大家自己实现,例子效果可参考下图:

  

浅谈Heatmap技术

 

  Heatmap

  BTW:热点可能会随着时间改变,为了能对照某个时间的网页,可以使用CutyCapt截屏。顺手再贴一个相关的项目:smt2(simple mouse tracking)。

  有关Heatmap的详细介绍,还可以参考

  How to make heat maps

  The definitive heatmap

  收工!Heatmap虽然不是很复杂的技术,但涉及的方面却很繁杂,希望本文能帮到大家。

以上是云栖社区小编为您精心准备的的内容,在云栖社区的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索的 , 自然界 蛇 ,以便于您获取更多的相关知识。