一、捕捉用户点击行为
这部分需要Javascript来实现。为了不陷入浏览器兼容的泥潭,可以选择JQuery:
<script> jQuery(document).ready(function() { $(document).mousedown(function(e) { if (e.clientX >= $(window).width() || e.clientY >= $(window).height()) { return; } $.get("/path/to/a/empty/html/file", { page_x : e.pageX, page_y : e.pageY, screen_width : screen.width, screen_height: screen.height }); }); }); </script>
之所以要记录屏幕分辨率是因为有的情况下需要修正点击坐标。比如说,一个居中显示的定宽的页面,其同一个位置在不同分辨率下的坐标是不同的,当渲染图片的时候,坐标需要以一个分辨率为准进行修正。另外,如果用户正在拖动滚动条,是不应该记录的。
二、分析客户端点击日志
客户端使用Ajax通过GET方法触发一个空HTML页面,如此就会在服务端留下日志:
page_x=...&page_y=...&screen_width=...&screen_height=...
不同的日志格式,结果会有所不同,这里仅仅以此为例来说明问题,本文采用AWK来解析日志,当然你也可以使用Perl或别的你熟悉的语言:
#!/usr/bin/awk -f BEGIN { FS="&"; } NF == 4 { param["page_x"] = "0"; param["page_y"] = "0"; param["screen_width"] = "0"; param["screen_height"] = "0"; split($0, query, "&"); for (key in query) { split(query[key], item, "="); if (item[1] in param) { param[item[1]] = item[2]; } } print "page_x:" , param["page_x"]; print "page_y:" , param["page_y"]; print "screen_" , param["screen_width"]; print "screen_height:", param["screen_height"]; print "\n"; }
至于数据的持久化,是使用MongoDB或者别的。
三、使用日志分析结果渲染图片
以Imagick为例,代码如下:
<?php $coordinates = array(); for ($i = 0; $i < 1000; $i++) { $coordinates[] = array(rand($i, 1000), rand($i, 1000)); } $max_repeat = max( array_count_values( array_map(function($v) { return "{$v[0]}x{$v[1]}"; }, $coordinates) ) ); $opacity = 1 - 1 / $max_repeat; $heatmap_image = new Imagick(); $heatmap_image->newImage(1000, 1000, new ImagickPixel('white')); $heatmap_image->setImageFormat('png'); $plot_image = new Imagick('plot.png'); $iterator = $plot_image->getPixelIterator(); foreach($iterator as $row) { foreach ($row as $pixel) { $colors = $pixel->getColor(); foreach (array('r', 'g', 'b') as $channel) { $color = $colors[$channel]; if ($color !== 255) { $colors[$channel] = $color + ((255 - $color) * $opacity); } } $pixel->setColor("rgb({$colors['r']},{$colors['g']},{$colors['b']})"); } $iterator->syncIterator(); } $plot_size = $plot_image->getImageGeometry(); foreach ($coordinates as $pair) { $heatmap_image->compositeImage( $plot_image, Imagick::COMPOSITE_MULTIPLY, $pair[0] - $plot_size['width'] / 2, $pair[1] - $plot_size['height'] / 2 ); } $color_image = new Imagick('clut.png'); $heatmap_image->clutImage($color_image); $heatmap_image->writeImage('heatmap.png'); ?>
代码虽然很多,但并不复杂,其中用到了两个图片,分别是:plot.png和clut.png。实际应用时,有时候点击量会非常大,此时没有必要把所有的点击都渲染出来,而应该采取随机取样的策略,如果采用MongoDB持久化的话,可以参考:The Random Attribute。
备注:代码参考image-tempest。
四、热力图的最终展现
形象一点来说,其实就是通过CSS+Javascript把生成的图片盖在网页上,并调节图片透明度来达到合二为一的效果。
有关Heatmap的详细介绍,还可以参考
Heatmap虽然不是很复杂的技术,但涉及的方面却很繁杂,希望本文能帮到大家。
开源热力图程序推荐:clickheat
基于clickheat开发的Heatmap plugin for Piwik:http://dev.piwik.org/trac/ticket/73
另外一块鼠标点击跟踪开源程序:http://code.google.com/p/smt2/
原文:网站点击热力图的技术实现.http://www.chinakdd.com/article-125829.html.2013-05-17