<?php
class simplemultibar
{
private $_yMaxPoints;
private $_stackBar;
private $_lineNeeded;
private $_pointsToIncrease;
public function __construct($height=600, $width=800)
{
$this->_yMaxPoints = 10;
$this->height = $height;
$this->width = $width;
$this->padding_width_percentage = 0.10;
$this->padding_height_percentage = 0.10;
$this->font = './verdanab.ttf';
$this->_initImage();
$this->bgColor = imagecolorallocate($this->image, 255, 255, 255);
$this->lineColor = imagecolorallocate($this->image, 128, 128, 128);
$this->yLabelColor = imagecolorallocate($this->image, 128, 0, 0);
$this->xLabelColor = imagecolorallocate($this->image, 130, 130, 130);
$this->barColor = imagecolorallocate($this->image, 0, 128, 0);
$this->_lineNeeded = true;
$this->multiData = false; /* to decide the data array is multi dimensional / not */
$this->showTotal = true;
$this->_stackBar = true;
$this->maxValue = 0;
$this->_pointsToIncrease = 0;
$this->barBgColorArr = array();
}
public function renderChart($dataArr=array(), $colorArr=array(), $title='')
{
$this->_setData($dataArr, $colorArr);
$this->_initPlotArea();
$this->_renderLines();
$this->_renderBars();
if ($this->multiData) {
$this->_renderLegends();
}
if ($title) {
$this->_renderTitle($title);
}
}
public function setStackBar($opt=false)
{
$this->_stackBar = $opt;
}
public function setLineNeeded($needed=true)
{
$this->_lineNeeded = $needed;
}
public function setPointsIncrements($points)
{
$this->_pointsToIncrease = $points;
}
public function setMaxPoints($point=20)
{
$this->_yMaxPoints = $point;
}
private function _initImage()
{
$this->image = imagecreatetruecolor($this->width, $this->height);
imagefilledrectangle($this->image, 0, 0, $this->width, $this->height, $this->bgColor);
}
private function _initPlotArea()
{
$width = $this->width;
if ($this->multiData) {
$width = ($this->width * 0.75);
}
$this->plotX1 = ($width * $this->padding_width_percentage);
$this->plotY1 = ($this->height * $this->padding_height_percentage);
$this->plotX2 = $width;
if (!$this->multiData) {
$this->plotX2 = ($width - $this->plotX1);
}
$this->plotY2 = ($this->height - $this->plotY1);
$this->graphHeight = $this->plotY2 - $this->plotY1;
$this->graphWidth = $this->plotX2 - $this->plotX1;
imageline($this->image, $this->plotX1, $this->plotY1, $this->plotX1, $this->plotY2, $this->lineColor);
imageline($this->image, $this->plotX1, $this->plotY2, $this->plotX2, $this->plotY2, $this->lineColor);
}
private function _renderTitle($title)
{
imagettftext($this->image, 10, 0, $this->plotX1, ($this->plotY1/2), $this->xLabelColor, $this->font, $title);
}
private function _renderLegends()
{
$availLegends = array();
foreach ($this->dataArr as $xlabel=>$xValue) {
$availLegends = array_merge($availLegends, array_diff(array_keys($xValue), $availLegends));
}
$x1 = $this->plotX2+10;
$y1 = $this->plotY1;
$x2 = $x1+15;
$y2 = $y1+20;
foreach ($availLegends as $legend) {
$color = isset($this->barBgColorArr[$legend])?$this->barBgColorArr[$legend]:$this->xLabelColor;
imagefilledrectangle($this->image, $x1, $y1, $x2, $y2, $color);
imagettftext($this->image, 8, 0, $x2+3, $y2-10, $this->xLabelColor, $this->font, $legend);
$y1 = $y2+2;
$y2 = $y2+20;
}
}
private function _setData($dataArr=array(), $colorArr=array())
{
$this->dataArr = $dataArr;
$this->setColorData($colorArr);
if (count($dataArr) == count($dataArr,1)) {
$this->maxValue = max($dataArr);
} else {
$this->multiData = true;
if ($this->_stackBar) {
foreach ($dataArr as $data) {
if ($this->maxValue < array_sum($data)) {
$this->maxValue = array_sum($data);
}
}
} else {
foreach ($dataArr as $data) {
if ($this->maxValue < max($data)) {
$this->maxValue = max($data);
}
}
}
}
}
function getBarColor($hex='#FFFFFF')
{
$color = str_replace('#','',$hex);
return imagecolorallocate($this->image, hexdec(substr($color,0,2)), hexdec(substr($color,2,2)), hexdec(substr($color,4,2)));
}
function setColorData($colorArr=array())
{
foreach ($colorArr as $index=>$colorValue) {
$this->barBgColorArr[$index] = $this->getBarColor($colorValue);
}
}
function _renderBars()
{
$barGap = ($this->graphWidth * 0.04); //4%
$barCount = count($this->dataArr);
//$barGap = 10; //gap between the bars 10px
$comboBarGap = 2; //2px;
$barGapWidth = ($barGap * count($this->dataArr));
if ($this->multiData && !$this->_stackBar) {
$barGapWidth += $comboBarGap * (count($this->dataArr, 1) - count($this->dataArr));
}
$availWidth = ($this->graphWidth - $barGapWidth);
$barWidth = ($availWidth / $barCount);
$x1 = $this->plotX1;
$x2 = $this->plotX1;
if ($this->multiData) {
if ($this->_stackBar) { /** stack bar */
foreach ($this->dataArr as $xlabel=>$xValue) {
$x1 = $x2+$barGap;
$x2 = $x1+$barWidth;
$this->drawBarLabel($x1, $barWidth, $xlabel);
$y1 = false;
$subValue1 = 0;
foreach ($xValue as $xSubLabel=>$xSubValue) {
$subValue1 += $xSubValue;
$y1 = $this->drawBar($x1, $x2, $barWidth, $subValue1, $xSubLabel, $x2+2, $y1, $xSubValue, 7);
}
}
} else { /** combo bar */
foreach ($this->dataArr as $xlabel=>$xValue) {
$x1+=$barGap;
$width = ($barWidth / count($xValue));
$this->drawBarLabel($x1, $barWidth, $xlabel);
foreach ($xValue as $xSubLabel=>$xSubValue) {
$x2 = $x1+$comboBarGap;
$x1 = $x2+$width;
$this->drawBar($x1, $x2, $width, $xSubValue, $xSubLabel, $x2);
}
}
}
} else { /** simple bar */
foreach ($this->dataArr as $xlabel=>$xValue) {
$x1 = $x2+$barGap;
$x2 = $x1+$barWidth;
$this->drawBar($x1, $x2, $barWidth, $xValue, $xlabel, $x1);
$this->drawBarLabel($x1, $barWidth, $xlabel);
}
}
}
function drawBarLabel($x1, $barWidth, $xlabel)
{
imagettftext($this->image, 9, 270, ($x1+($barWidth/2)), $this->plotY2+3, $this->xLabelColor, $this->font, $xlabel);
}
private function drawBar($x1, $x2, $barWidth, $xValue, $xlabel, $xTotal, $y1=false, $total=0, $totalPos=false)
{
$color = isset($this->barBgColorArr[$xlabel])?$this->barBgColorArr[$xlabel]:$this->xLabelColor;
$y1 = ($y1)?$y1:$this->plotY2;
$y1 -= 1;
$y2 = $this->plotY1 + ($this->graphHeight - $this->pointsToPixels($xValue, $this->maxValue, $this->graphHeight));
imagefilledrectangle($this->image, $x1, $y1, $x2, $y2, $color);
if ($this->showTotal) {
$total = ($total)?$total:$xValue;
$totalPos = $totalPos?($y2+$totalPos):$y2-3;
imagettftext($this->image, 7, 0, ($xTotal), $totalPos, $this->xLabelColor, $this->font, $total);
}
return $y2;
}
private function _renderLines()
{
if ($this->_pointsToIncrease <= 0) { /** Not yet set. so set it */
if ($this->maxValue > ($this->_yMaxPoints)) {
$this->_pointsToIncrease = ($this->maxValue/$this->_yMaxPoints);
} else {
$this->_pointsToIncrease = 1;
$this->_yMaxPoints = $this->maxValue;
}
}
if ($this->_lineNeeded) {
$pointYIncrementor = round($this->graphHeight / $this->_yMaxPoints);
$y = $this->plotY2;
$labelXPosition = round($this->plotX1 / 3); /* dividing the padding space into 3 divisions and starting the text at first division */
for($i=0; $i < $this->maxValue; $i+=$this->_pointsToIncrease) {
imagettftext($this->image, 9, 0, $labelXPosition, $y, $this->yLabelColor, $this->font, $i);
imageline($this->image, $this->plotX1-5, $y, $this->plotX2, $y, $this->lineColor);
$y -= $pointYIncrementor;
}
}
}
function pointsToPixels($numamount, $numtotal, $for=100)
{
$barCount1 = $numamount / $numtotal;
$barCount2 = $barCount1 * $for;
return number_format($barCount2, 0);
}
public function renderImage()
{
header("content-type:image/png");
imagepng($this->image);
}
}
/*
$dataArr['2006']=array('sachin'=>3, 'Lara'=>1, 'Ponting'=>2, 'Jacques Kallis'=>1);
$dataArr['2007']=array('sachin'=>1, 'Lara'=>1, 'Ponting'=>1, 'Jacques Kallis'=>3);
$dataArr['2008']=array('sachin'=>4, 'Lara'=>5, 'Ponting'=>2, 'Jacques Kallis'=>5);
$dataArr['2009']=array('sachin'=>9, 'Lara'=>5, 'Ponting'=>2, 'Jacques Kallis'=>8, 'Rahul Dravid'=>7, 'Sourav Ganguly'=>7);
$dataArr['2010']=array('sachin'=>7, 'Lara'=>3, 'Ponting'=>3);
$dataArr['2011']=array('sachin'=>6, 'Lara'=>2, 'Ponting'=>1);
$colorArr['sachin']='#5CB3FF';
$colorArr['Lara']='#F6358A';
$colorArr['Ponting']='#7D1B7E';
$colorArr['Jacques Kallis']='#FBB917';
$colorArr['Rahul Dravid']='#F87217';
$colorArr['Sourav Ganguly']='#009417';
$bar = new simplemultibar(728, 1200);
$bar->setStackBar(true); /** Combo chart */
//$bar->setStackBar(true); /** Stack chart */
$bar->renderChart($dataArr, $colorArr, 'Batsmen & Centuries (2008-2010)'); /** Combo / Stack chart */
//$simpleDataArr=array_combine(range(2001, 2010), range(100, 1000, 100));
//$bar->setMaxPoints(1010)
//$bar->renderChart($simpleDataArr, $colorArr=array(), 'Total Sales report'); /** Simple chart chart */
$bar->renderImage();
*/
|