files[] = $file; } } /** * Do some tasks before drawing (database connection...) */ public function startDrawing() { return true; } /** * Find pixels coords and draw these on the current image * * @param integer $image Number of the image (to be used with $this->height) * @return boolean Success */ public function drawPixels($image) { /** * If it's not the first image, * just use the value stored in the temp files */ if ($image !== 0) { if (file_exists($this->cache.sprintf($this->file, $image).'_log')) { $f = fopen($this->cache.sprintf($this->file, $image).'_log', 'r'); while (feof($f) === false) { $click = explode('|', trim(fgets($f, 1024))); if (count($click) === 3) { $x = (int) $click[0]; $y = (int) $click[1]; $c = (bool) $click[2]; if ($this->heatmap) { /** * Apply a calculus for the step, * with increases the speed of rendering: * step = 3, then pixel is drawn at x = 2 (center of a 3x3 square) */ $x -= $x % $this->step - $this->startStep; $y -= $y % $this->step - $this->startStep; /** * Add 1 to the current color of this pixel * (color which represents the sum of clicks on this pixel) */ $color = imagecolorat($this->image, $x, $y) + 1; imagesetpixel($this->image, $x, $y, $color); $this->maxClicks = max($this->maxClicks, $color); } else { /** Put a red or green cross at the click location */ $color = $c === true ? 0xFF0000 : 0x00DC00; imageline($this->image, $x - 2, $y - 2, $x + 2, $y + 2, $color); imageline($this->image, $x + 2, $y - 2, $x - 2, $y + 2, $color); } } } fclose($f); unlink($this->cache.sprintf($this->file, $image).'_log'); } return true; } $leftWidth = 10;//(int) $this->layout[1]; $centerWidth = 0;//(int) $this->layout[2]; $rightWidth = 0;//(int) $this->layout[3]; if ($leftWidth !== 0 && $centerWidth !== 0 && $rightWidth === 0) { /** * Fixed left menu and fixed center ? * Fall back to a fixed left menu only */ $leftWidth += $centerWidth; $centerWidth = 0; } elseif ($leftWidth === 0 && $centerWidth !== 0 && $rightWidth !== 0) { /** * Fixed right menu and fixed center ? * Fall back to a fixed right menu only */ $rightWidth += $centerWidth; $centerWidth = 0; } elseif ($leftWidth !== 0 && $centerWidth !== 0 && $rightWidth !== 0) { /** * Everything is fixed ?? */ return $this->raiseError(LANG_ERROR_FIXED); } $totalWidth = $leftWidth + $centerWidth + $rightWidth; for ($file = 0; $file < count($this->files); $file++) { /** Read clicks in the log file */ $f = @fopen($this->files[$file], 'r'); if ($f === false) { return $this->raiseError(LANG_ERROR_FILE.': '.$this->files[$file]); } $buffer = ''; $count = 0; while (true) { $buffer .= fgets($f, 1024); // Grouping by 1000 clicks if (feof($f) === false && $count++ !== 1000) continue; /** Do a regular match (faster and easier for large volume of data) */ preg_match_all('~^(\d+)\|(\d+)\|(\d+)\|(\d+)$~m', $buffer, $clicks); $buffer = ''; for ($i = 0, $max = count($clicks[1]); $i < $max; $i++) { $x = (int) $clicks[1][$i]; // X $y = (int) $clicks[2][$i]; // Y $w = (int) $clicks[3][$i]; // display width $c = ($clicks[4][$i] < 3); // left click /** * X is not in the range of sizes, * or right click for heatmap, * or X is greater than screen size, * the website is too large for the window, * so we don't know where the click is... ignore those clicks */ if ($x <= $this->minScreen || $x > $this->maxScreen || $this->heatmap && $c === false || $x > $w) continue; /** * Correction of X for liquid and/or fixed layouts */ if ($w <= $totalWidth) { /** * Display's width is less than fixed content's one, * X is absolute */ } elseif ($leftWidth !== 0 && $centerWidth === 0 && $rightWidth === 0) { // Left fixed menu if ($x <= $leftWidth) { // Click in the left menu: X is good } else { // Apply a percentage on the rest of the screen $x = $leftWidth + ceil(($this->width - $leftWidth) * ($x - $leftWidth) / ($w - $leftWidth)); } } elseif ($leftWidth === 0 && $centerWidth === 0 && $rightWidth !== 0) { // Right fixed menu if ($w - $x <= $rightWidth) /** * Click in the right menu: * X is good, but relative to the right border */ $x = $this->width - ($w - $x); else /** * Apply a percentage on the rest of the screen */ $x = ceil(($this->width - $rightWidth) * $x / ($w - $rightWidth)); } elseif ($leftWidth !== 0 && $centerWidth === 0 && $rightWidth !== 0) { // Left and right fixed menus if ($w - $x <= $rightWidth) { /** * Click in the right menu: * X is good, but relative to the right border */ $x = $this->width - ($w - $x); } elseif ($x <= $leftWidth) { /** * Click in the left menu: X is good */ } else { /** * Apply a percentage on the rest of the screen */ $x = $leftWidth + ceil(($this->width - $leftWidth - $rightWidth) * ($x - $leftWidth) / ($w - $leftWidth - $rightWidth)); } } elseif ($leftWidth === 0 && $centerWidth !== 0 && $rightWidth === 0) { // Fixed centered content if (abs($x - $w / 2) <= $centerWidth / 2) /** * Click is in the centered content */ $x = ($this->width - $w) / 2 + $x; elseif ($x < $w / 2) /** * Click is at the left of the centered content */ $x = ($this->width - $centerWidth) / ($w - $centerWidth) * $x; else /** * Click is at the right of the centered content */ $x = ($this->width + $centerWidth) / 2 + ($this->width - $centerWidth) / ($w - $centerWidth) * ($x - ($w + $centerWidth) / 2); } else { /** * Layout 100% */ $x = $this->width / $w * $x; } $x = (int) $x; $y = (int) $y; if ($x < 0 || $x >= $this->width) continue; if ($y >= 0 && $y < $this->height) { if ($this->heatmap) { /** * Apply a calculus for the step, * with increases the speed of rendering: * step = 3, then pixel is drawn at x = 2 (center of a 3x3 square) */ $x -= $x % $this->step - $this->startStep; $y -= $y % $this->step - $this->startStep; /** * Add 1 to the current color of this pixel * (color which represents the sum of clicks on this pixel) */ $color = imagecolorat($this->image, $x, $y) + 1; imagesetpixel($this->image, $x, $y, $color); $this->maxClicks = max($this->maxClicks, $color); } else { /** * Put a red or green cross at the click location */ $color = $c === true ? 0xFF0000 : 0x00DC00; imageline($this->image, $x - 2, $y - 2, $x + 2, $y + 2, $color); imageline($this->image, $x + 2, $y - 2, $x - 2, $y + 2, $color); } } else { // Append to the temporary log of this image error_log($x.'|'.($y % $this->height).'|'.$c."\n", 3, $this->cache . sprintf($this->file, ceil($y / $this->height) - 1).'_log'); } /** * Looking for the maximum height of click */ $this->maxY = max($y, $this->maxY); } unset($clicks); if ($count !== 1001) break; $count = 0; } fclose($f); } return true; } /** * Do some cleaning or ending tasks (close database, reset array...) */ function finishDrawing() { $this->files = array(); return true; } } ?>