Tuesday, September 1, 2009

PHP GD Heatmap Generation

I recently set out to write my own tools to generate a heatmap from clicks on my websites. So far the collection of click positions has been a little tricky because of things like the visitors screen being a different size than mine, javascript being enabled but Adsense being blocked which shifts the position of some elements, and a whole host of other annoyances that don't come to mind at the moment.

One thing that did come sort of easy was figuring out how to generate a heatmap image using the PHP GD image functions and x/y pairs from clicks. At first I was wondering how to get the three color areas without having later clicks overlap other clicks and throw off the flow of the colors.

Rather than working with a click at a time, I needed to generate the heatmap image one color and one click at a time. I would need to loop through the image three times, each time drawing progressively smaller circles using different colors.

I put together a simple function to draw a heatmap onto an image using a list of x/y points and an image created using GD.


function draw_heatmap($image, &$clicks)
{// Only available with compiled in version of GD
imageantialias($image, true);

// Heatmap colors
$cold = imagecolorallocate($image, 0, 0, 255);
$warm = imagecolorallocate($image, 0, 255, 0);
$hot = imagecolorallocate($image, 255, 0, 0);

// Loop through the clicks and draw the largest/coldest circles first
foreach($clicks as $click)
imagefilledellipse($image, $click['x'], $click['y'], 30, 30, $cold);

// Next draw middle/warm circles over the cold ones
foreach($clicks as $click)
imagefilledellipse($image, $click['x'], $click['y'], 20, 20, $warm);

// Finally draw the smallest/hot circles over everything
foreach($clicks as $click)
imagefilledellipse($image, $click['x'], $click['y'], 10, 10, $hot);

return true;

$width = 200;
$height = 200;
$image = imagecreatetruecolor($width, $height);
$clicks = array(
array('x' => 123, 'y' => 123),
array('x' => 45, 'y' => 113)
draw_heatmap($image, $clicks);
header('Content-Type: image/png');


No comments: