<?php<br />
/* <br />
* 定义 柱状图(柱形图) 类<br />
* 注意,使用前请确保字体路径存在并允许访问,如果出错,还要检查在php.ini配置中的open_basedir项,如果没此路径请添加,或在程序中设置包含<br />
* 智能化的柱状图程序,用于报表等<br />
***/<br />
<br />
define("DEFAULT_FONT_PATH", "c:/windows/fonts/simhei.ttf");<br />
class SingleBar<br />
{<br />
private $_x;<br />
private $_y;<br />
private $_h;<br />
public $_l = 50;<br />
private $_w = null;<br />
private $_srcPoints = array();<br />
private $_points = array();<br />
<br />
public function __construct($x, $y, $h, $l = 50, $w = null)<br />
{<br />
$this->_x = $x;<br />
$this->_y = $y;<br />
$this->_h = $h;<br />
$this->_l = $l;<br />
$this->_w = $w;<br />
$this->_srcPoints = $this->getSrcPoints();<br />
$this->_points = $this->getPoints();<br />
}<br />
<br />
public function getSrcPoints()<br />
{<br />
return array(<br />
array($this->_x , $this->_y),<br />
array($this->_x+$this->_l , $this->_y),<br />
array($this->_x+(1.35*$this->_l), $this->_y-(0.35*$this->_l)),<br />
array($this->_x+(0.35*$this->_l), $this->_y-(0.35*$this->_l)),<br />
array($this->_x , $this->_y+$this->_h),<br />
array($this->_x+$this->_l , $this->_y+$this->_h),<br />
array($this->_x+(1.35*$this->_l), $this->_y+$this->_h-(0.35*$this->_l)) <br />
);<br />
}<br />
<br />
public function getPoints()<br />
{<br />
$points = array();<br />
foreach($this->_srcPoints as $key => $val)<br />
{<br />
$points[] = $val[0];<br />
$points[] = $val[1];<br />
}<br />
return $points;<br />
}<br />
<br />
public function getTopPoints()<br />
{<br />
return array_slice($this->_points, 0, 8); //顶坐标<br />
}<br />
<br />
public function getBelowPoints()<br />
{<br />
return array_merge(array_slice($this->_points, 0, 2), array_slice($this->_points, 8, 4), array_slice($this->_points, 2, 2)); //下坐标<br />
}<br />
<br />
public function getRightSidePoints()<br />
{<br />
return array_merge(array_slice($this->_points, 2, 2), array_slice($this->_points, 10, 4), array_slice($this->_points, 4, 2)); //右侧坐标<br />
}<br />
<br />
public function draw($image, $topColor, $belowColor, $sideColor, $borderColor = null, $type = 'LEFT')<br />
{<br />
if (is_null($borderColor))<br />
{<br />
$borderColor = 0xcccccc;<br />
}<br />
<br />
$top_rgb = $this->getRGB($topColor);<br />
$below_rgb = $this->getRGB($belowColor);<br />
$side_rgb = $this->getRGB($sideColor);<br />
$top_color = imagecolorallocate($image, $top_rgb['R'], $top_rgb['G'], $top_rgb['B']);<br />
$below_color = imagecolorallocate($image, $below_rgb['R'], $below_rgb['G'], $below_rgb['B']);<br />
$side_color = imagecolorallocate($image, $side_rgb['R'], $side_rgb['G'], $side_rgb['B']);<br />
<br />
imagefilledpolygon($image, $this->getTopPoints(), 4, $top_color); //画顶面<br />
imagepolygon($image, $this->getTopPoints(), 4, $borderColor); //画顶面边线<br />
<br />
imagefilledpolygon($image, $this->getBelowPoints(), 4, $below_color); //画下面<br />
imagepolygon($image, $this->getBelowPoints(), 4, $borderColor); //画下面边线<br />
<br />
if ($type == 'LEFT')<br />
{<br />
imagefilledpolygon($image, $this->getRightSidePoints(), 4, $side_color); //画右侧面<br />
imagepolygon($image, $this->getRightSidePoints(), 4, $borderColor); //画侧面边线<br />
} <br />
}<br />
<br />
public function getRGB($color)<br />
{<br />
$ar = array();<br />
$color = hexdec($color);<br />
$ar['R'] = ($color>>16) & 0xff;<br />
$ar['G'] = ($color>>8) & 0xff;<br />
$ar['B'] = ($color) & 0xff;<br />
return $ar;<br />
}<br />
}<br />
<br />
class Bar<br />
{<br />
private $_W;<br />
private $_H;<br />
private $_bgColor = "ffffff";<br />
private $_barHeights = array();<br />
private $_barTexts = array();<br />
private $_barColors = array();<br />
public $_title;<br />
public $_paddingTop = 30;<br />
public $_paddingBottom = 100;<br />
public $_paddingLeft = 45;<br />
public $_paddingRight = 2;<br />
public $_barL = 50;<br />
public $image;<br />
<br />
public function __construct($imgW, $imgH, $barHeights, $barTexts = null, $barColors = null)<br />
{<br />
$this->_W = $imgW;<br />
$this->_H = $imgH;<br />
$this->_barHeights = $barHeights;<br />
$this->_barTexts = $barTexts;<br />
$this->_barColors = $barColors;<br />
$this->_paddingBottom = $this->resetPaddingBottom();<br />
$this->_H = $this->resetHeight();<br />
$this->image = imagecreatetruecolor($this->_W, $this->_H);<br />
}<br />
<br />
public function stroke()<br />
{<br />
$this->drawBg();<br />
$this->drawBars();<br />
$this->drawTitle();<br />
$this->drawLables();<br />
ob_start();<br />
//header("Content-type: image/png");<br />
//imagepng($this->image);<br />
header("Content-type: " . image_type_to_mime_type(IMAGETYPE_JPEG));<br />
imagejpeg($this->image);<br />
imagedestroy($this->image);<br />
}<br />
<br />
public function drawBg()<br />
{<br />
$img_w = $this->_W;<br />
$img_h = $this->_H;<br />
$paddingTop = $this->_paddingTop;<br />
$paddingBottom = $this->_paddingBottom;<br />
$paddingLeft = $this->_paddingLeft;<br />
$paddingRight = $this->_paddingRight;<br />
$rgb = $this->getRGB($this->_bgColor);<br />
$bg = imagecolorallocate($this->image,$rgb['R'], $rgb['G'], $rgb['B']);<br />
imagefilledrectangle($this->image, 0, 0, $img_w, $img_h, $bg);<br />
$side_bg = imagecolorallocatealpha($this->image, 220, 220, 220, 75);<br />
$side_bg2 = imagecolorallocate($this->image, 220, 220, 220);<br />
$border_color = imagecolorallocate($this->image, 190, 190, 190);<br />
$line_color = imagecolorallocate($this->image, 236, 236, 236);<br />
$dial_color = imagecolorallocate($this->image, 131, 131, 131);<br />
<br />
$x1 = $paddingLeft;<br />
$y1 = $paddingTop;<br />
$x2 = $img_w - $paddingRight;<br />
$y2 = $img_h - $paddingBottom;<br />
imagerectangle($this->image, $x1, $y1, $x2, $y2, $border_color);<br />
imagefilledpolygon($this->image, array($x1-5,$y1+10, $x1-5,$y2+10, $x1,$y2, $x1,$y1), 4, $side_bg);<br />
imagepolygon($this->image, array($x1-5,$y1+10, $x1-5,$y2+10, $x1,$y2, $x1,$y1), 4, $border_color);<br />
imagefilledpolygon($this->image, array($x1-5,$y2+10, $x2-5,$y2+10, $x2,$y2, $x1,$y2), 4, $side_bg);<br />
imagepolygon($this->image, array($x1-5,$y2+10, $x2-5,$y2+10, $x2,$y2, $x1,$y2), 4, $border_color);<br />
imageline($this->image, $x1, $y2, $x2, $y2, $side_bg2);<br />
<br />
$total_h = $img_h - $paddingTop - $paddingBottom;<br />
$every_h = $total_h/11;<br />
for($i=1; $i<=10; $i++)<br />
{<br />
imageline($this->image, $x1, $y1+($every_h*$i), $x2, $y1+($every_h*$i), $line_color); //画网线<br />
}<br />
<br />
$max_h = max($this->_barHeights);<br />
for($i=1; $i<=10; $i++)<br />
{<br />
$value = $max_h - (($max_h/10)*($i-1));<br />
$value = strval($value);<br />
$str_w = strlen($value)*5;<br />
imageline($this->image, $x1-5-3, $y1+10+($every_h*$i), $x1-3+1, $y1+10+($every_h*$i), $dial_color); //画刻度线<br />
imagestring($this->image, 3, $x1-5-3-$str_w-1, $y1+10+($every_h*$i)-5, $value, 0x000000);<br />
}<br />
}<br />
<br />
<br />
public function drawBars()<br />
{<br />
$counts = count($this->_barHeights);<br />
if (empty($this->_barColors))<br />
{<br />
$color = $this->setColor();<br />
$this->_barColors = array_slice($color, 0, $counts);<br />
//shuffle($this->_barColors);<br />
}<br />
$every_w = ($this->_W - $this->_paddingLeft - $this->_paddingRight)/$counts; //每一段宽<br />
$barL = $every_w;<br />
$barL = ($barL > $this->_barL*1.35+6) ? $this->_barL : $barL/1.35 - 6;<br />
$max_h = max($this->_barHeights);<br />
$ruler_h = $this->_H - $this->_paddingTop - $this->_paddingBottom; //标尺总高度<br />
$stander_h = $ruler_h - ($ruler_h/11); //标尺10等分的高度<br />
$i = 0;<br />
foreach ($this->_barHeights as $val)<br />
{<br />
$h = ($stander_h/$max_h)*$val;<br />
$x = $this->_paddingLeft + ($every_w*$i) + (($every_w - ($barL*1.35))/2);;<br />
$y = $this->_H - $this->_paddingBottom + 10 - $h;<br />
//$t_color = $this->_barColors[$i];<br />
$b_color = $this->_barColors[$i];<br />
//$s_color = $this->_barColors[$i];<br />
<br />
<br />
$rgb = $this->getRGB($this->_barColors[$i]);<br />
$R = $rgb['R'] * 0.7;<br />
$G = $rgb['G'] * 0.7;<br />
$B = $rgb['B'] * 0.7;<br />
<br />
$c1 = $R > 0 ? dechex($R) : '00';<br />
$c2 = $G > 0 ? dechex($G) : '00';<br />
$c3 = $B > 0 ? dechex($B) : '00';<br />
<br />
$t_color = $b_color;<br />
$s_color = $c1. $c2 . $c3;<br />
<br />
$SingleBar = new SingleBar($x, $y, $h, $barL);<br />
$SingleBar->draw($this->image, $t_color, $b_color, $s_color);<br />
$i++;<br />
}<br />
}<br />
<br />
public function drawTitle()<br />
{<br />
if (empty($this->_title))<br />
{<br />
return;<br />
}<br />
$font = 5;<br />
$font_w = imagefontwidth($font);<br />
$len = strlen($this->_title);<br />
$x = ($this->_W + $this->_paddingLeft - $this->_paddingRight)/2;<br />
$x -= ($len*$font_w)/2;<br />
$y = ($this->_paddingTop - $font_w)/2 + 12;<br />
//imagestring($this->image, $font, $x, $y, $title, 0x000000);<br />
imagettftext($this->image, 12, 0, $x, $y, 0x000000, DEFAULT_FONT_PATH, $this->_title);<br />
}<br />
<br />
public function drawLables()<br />
{<br />
$x1 = $this->_paddingLeft - 5;<br />
$y1 = $this->_H - $this->_paddingBottom + 20;<br />
$x2 = $this->_W - $this->_paddingRight;<br />
$y2 = $this->_H - 10;<br />
//imagefilledrectangle($this->image, $x1, $y1, $x2, $y2, 0xffffff);<br />
imagerectangle($this->image, $x1, $y1, $x2, $y2, 0x000000);<br />
$space = 5;<br />
$x = $x1 + 3;<br />
$y = $y1 + 3;<br />
foreach ($this->_barTexts as $key => $val)<br />
{<br />
$color = $this->_barColors[$key];<br />
$rgb = $this->getRGB($color);<br />
$bg = imagecolorallocate($this->image,$rgb['R'], $rgb['G'], $rgb['B']);<br />
imagefilledrectangle($this->image, $x, $y, $x+12, $y+12, $bg); //绘12*12的矩形<br />
imagerectangle($this->image, $x, $y, $x+12, $y+12, 0x000000); //绘12*12的矩形框<br />
imagettftext($this->image, 12, 0, $x+12+3, $y+12, 0x000000, DEFAULT_FONT_PATH, $val);<br />
$x += 12 + $space + (strlen($val)*8) + $space;<br />
if ($x + (strlen($val)*8) >= $this->_W - $this->_paddingLeft - $this->_paddingRight)<br />
{<br />
$x = $x1 + 3;<br />
$y = $y + 12 + 3;<br />
}<br />
}<br />
}<br />
<br />
public function resetPaddingBottom()<br />
{<br />
$ruler_w = $this->_W - $this->_paddingLeft - $this->_paddingRight;<br />
$label_w = $this->getLableTotalWidth();<br />
$lines = ceil($label_w / $ruler_w);<br />
$h = 12 * $lines + (3 * ($lines + 1)) + 30;<br />
return $h;<br />
}<br />
<br />
public function resetHeight()<br />
{<br />
$padding_bottom = $this->resetPaddingBottom();<br />
if ($this->_H - $padding_bottom < 222)<br />
{<br />
return 222 + $padding_bottom;<br />
}<br />
return $this->_H;<br />
}<br />
<br />
<br />
public function getLableTotalWidth()<br />
{<br />
$counts = count($this->_barTexts);<br />
$space = 5;<br />
$total_len = 0;<br />
foreach ($this->_barTexts as $val)<br />
{<br />
$total_len += strlen($val);<br />
}<br />
<br />
$tx_w = ($total_len * 9) + ((12 + 3 + $space) * $counts);<br />
return $tx_w;<br />
}<br />
<br />
public function setBg($color)<br />
{<br />
$this->_bgColor = $color;<br />
}<br />
<br />
public function setTitle($title)<br />
{<br />
$this->_title = $title;<br />
}<br />
<br />
public function setColor()<br />
{<br />
$ar = array('ff', '00', '33', '66', '99', 'cc');<br />
$color = array();<br />
for ($i=0; $i<6; $i++)<br />
{<br />
for ($j=0; $j<6; $j++)<br />
{<br />
for($k=0; $k<6; $k++)<br />
{<br />
$color[] = $ar[$i] . $ar[$j] . $ar[$k];<br />
}<br />
}<br />
}<br />
<br />
$color2 = array();<br />
for ($i=1; $i<216; $i += 4)<br />
{<br />
$color2[] = $color[$i];<br />
}<br />
<br />
return $color2;<br />
}<br />
<br />
public function getRGB($color)<br />
{<br />
$ar = array();<br />
$color = hexdec($color);<br />
$ar['R'] = ($color>>16) & 0xff;<br />
$ar['G'] = ($color>>8) & 0xff;<br />
$ar['B'] = ($color) & 0xff;<br />
return $ar;<br />
}<br />
}<br />
<br />
/***/<br />
$bar = new Bar(500, 300, array(600, 300, 30, 500, 400, 250, 350, 360), array('AAAAA', 'BBBBB', 'CCCCC', 'DDDDD', 'EEEEEE', 'FFFFFF', 'GGGGGGG', 'HHHHHHHHH'));<br />
$bar->setTitle('打造完美柱状图!');<br />
$bar->stroke();<br />
/***/<br />
?>