您的位置:首页 > 编程语言 > PHP开发

利用php实现数据统计图

2011-03-20 10:31 639 查看
年前由于工作需要,工作的中心由asp转到了php开发上,通过几周的学习与实践,已基本能熟练设计常用的web功能。b/s架构的web应用程序实现原理是一样的,不同的是脚本语法、解析方式等方面。

php在图片处理方面提供了强劲的支持。通过对php技术手册的翻阅,发现在php内置函数与GD库支持下,可以方便创建、操作各种图片,在asp下则需要如aspjpeg类的第三方组件(本人不会写组件)才能完成。而且感觉php在oo方面也很方便,于是趁热打铁写了个数据统计图类,功能与生成效果还是很简陋的那种,呵呵。下面分享给博客园的朋友,类中的WEBSITE_DIRROOT换成你的网站根目录路径,欢迎路过的大牛拍砖指导^^

<?php
/*
* class: 数据统计图
* author: 51JS.COM-ZMM
* date: 2011.2.1
* email: 304924248@qq.com
* blog: http://www.cnblogs.com/cnzmm/ */

class Draw {
public $mass=10, $unit=10, $data=array(), $save=false, $dir='/images/count';
private $width=0, $height=0, $side=0, $bgcor=array(255, 255, 255);
private $name, $image, $offset=0, $margin=20, $space=3, $font='/fonts/simsun.ttc';
private $fontW, $fontH, $fontC, $fontA, $osSum, $omSum, $xLen, $yLen, $size=9;

function __construct($width=0, $height=0, $data=array()) {
$this->width = $width;
$this->height = $height;
if (!empty($data)) $this->data = $data;

$this->fontW = imagefontwidth(2);
$this->fontH = imagefontheight(2);
$this->fontA = imagefontheight($this->size);
$this->fontA = round($this->fontA / 2) + 2;

$this->font = WEBSITE_DIRROOT.$this->font;
if (!is_file($this->font)) {
exit('字体文件不存在!');
} else {
$this->font = realpath($this->font);
}
}

public function DrawPie($name="") {
$this->SetImgName($name);

$this->side = $this->width;
if ($this->side > 0 && !empty($this->data)) {
$pie_core = $this->side / 2;

$fts_max = 0;
foreach (array_keys($this->data) as $item) {
$chk_itm = $item.' '.max($this->data).' 00.00%';
$fts_box = imagettfbbox($this->size, 0, $this->font, $chk_itm);
$chk_len = $fts_box[4] - $fts_box[6];
if ($chk_len > $fts_max) $fts_max = $chk_len;
} $pie_cAdd = 48 + $fts_max;

$this->image = @imagecreate($this->side + $pie_cAdd, $this->side + 1);
if ($this->image) {
$this->SetDftColor();

$dat_sum = array_sum($this->data);
$arc_beg = array(-180, -90, 0, 90, 180);
$arc_beg = $arc_beg[array_rand($arc_beg)];

$fts_add = $this->fontA * 2;
$ftx_beg = $this->side + 28; $fty_beg = 2;
$ftx_add = 20; $fty_add = 20;
$fts_cor = imagecolorallocate($this->image, 0, 0, 0);
$fty_chk = $fty_add * count($this->data);
while ($fty_chk > $this->side + 2) {
$fty_chk = --$fty_add * count($this->data);
}

foreach ($this->data as $item => $data) {
$rnd_cor = $this->GetRndColor();
$arc_pct = number_format($data * 100 / $dat_sum, 2);
$arc_end = $data * 360 / $dat_sum + $arc_beg;
$item = iconv('gb2312', 'UTF-8', (string)$item);

imagefilledarc($this->image, $pie_core, $pie_core, $this->side, $this->side, $arc_beg, $arc_end, $rnd_cor, IMG_ARC_PIE);
imagefilledrectangle($this->image, $ftx_beg, $fty_beg, $ftx_beg + 12, $fty_beg + 10, $rnd_cor);
imagettftext($this->image, $this->size, 0, $ftx_beg + $ftx_add, $fty_beg + $this->fontA, $fts_cor, $this->font, $item.' '.$data.' '.$arc_pct.'%');

$fty_beg += $fty_add; $arc_beg = $arc_end;
}

$this->Output();
}
} else {
exit('画布边长设置不正确或统计数据为空!');
}
}

public function DrawColumn($name="") {
$this->SetImgName($name);

if (!empty($this->data)) {
$this->DrawCdtAxes();
$this->DrawLattice();

$cdx_cut = count($this->data);
$cdx_add = floor($this->xLen / $cdx_cut);
$cdy_add = $this->yLen / $this->mass;
imagesetthickness($this->image, floor($cdx_add / 2));

$cdy_end = $this->height - $this->osSum - 1;
$cdx_beg = floor($cdx_add / 2) + $this->osSum;
foreach ($this->data as $item => $data) {
$cdy_beg = $this->yLen - ($data * $cdy_add / $this->unit) + $this->omSum;
imageline($this->image, $cdx_beg, $cdy_beg, $cdx_beg, $cdy_end, $this->GetRndColor());

$fts_txt = (string)$data;
$ftx_beg = $cdx_beg - $this->fontW * strlen($fts_txt) / 2;
$fty_beg = $cdy_beg - $this->fontH - $this->space;
imagestring($this->image, 2, $ftx_beg, $fty_beg, $fts_txt, $this->fontC);

$fts_txt = iconv('gb2312', 'UTF-8', (string)$item);
$fts_box = imagettfbbox($this->size, 0, $this->font, $fts_txt);
$ftx_beg = $cdx_beg - floor($fts_box[4] - $fts_box[6]) / 2;
$fty_beg = $this->height - $this->offset + $this->fontA;
imagettftext($this->image, $this->size, 0, $ftx_beg, $fty_beg, $this->fontC, $this->font, $fts_txt);

$cdx_beg += $cdx_add;
}

$this->Output();
} else {
exit('统计数据为空!');
}
}

public function DrawLine($name="") {
$this->SetImgName($name);

if (!empty($this->data)) {
$this->DrawCdtAxes();
$this->DrawLattice();

$dat_idx = 0;
$cd_line = imagecolorallocate($this->image, 255, 0, 0);
$cd_fold = imagecolorallocate($this->image, 0, 0, 255);

$cdx_cut = count($this->data) - 1;
$cdx_add = floor($this->xLen / $cdx_cut);
$cdy_add = $this->yLen / $this->mass;

$cdx_old = 0; $cdx_beg = $this->osSum;
$cdy_old = 0; $cdy_beg = $this->omSum - 5;
$cdy_end = $this->height - $this->osSum - 1;
foreach ($this->data as $item => $data) {
imagesetthickness($this->image, 1);
$dat_idx > 0 && imageline($this->image, $cdx_beg, $cdy_beg, $cdx_beg, $cdy_end, IMG_COLOR_STYLED);
imagesetthickness($this->image, 2);

$cdx_dot = $cdx_beg;
$cdy_dot = $this->yLen - $data * $cdy_add / $this->unit + $this->omSum;
if ($cdx_old > 0 && $cdy_old > 0) {
imageline($this->image, $cdx_old, $cdy_old, $cdx_dot, $cdy_dot, $cd_line);
imagefilledellipse($this->image, $cdx_old, $cdy_old, 6, 6, $cd_fold);
}
imagefilledellipse($this->image, $cdx_dot, $cdy_dot, 6, 6, $cd_fold);

$fts_txt = '('.(string)$data.')';
if ($dat_idx == 0) {
$ftx_beg = $cdx_dot + $this->space + 3;
$fty_beg = $cdy_dot - $this->fontH / 2;
} else {
$ftx_beg = $cdx_dot - $this->fontW * strlen($fts_txt) / 2;
$fty_beg = $cdy_dot - $this->fontH - $this->space * 2;
}
imagestring($this->image, 2, $ftx_beg, $fty_beg, $fts_txt, $this->fontC);

$fts_txt = iconv('gb2312', 'UTF-8', (string)$item);
$fts_box = imagettfbbox($this->size, 0, $this->font, $fts_txt);
$ftx_beg = $cdx_beg - floor($fts_box[4] - $fts_box[6]) / 2;
$fty_beg = $this->height - $this->offset + $this->fontA;
imagettftext($this->image, $this->size, 0, $ftx_beg, $fty_beg, $this->fontC, $this->font, $fts_txt);

$dat_idx ++; $cdx_beg += $cdx_add;
$cdx_old = $cdx_dot; $cdy_old = $cdy_dot;
}

$this->Output();
} else {
exit('统计数据为空!');
}
}

public function GetImgName() {
return empty($this->name) ? null :
WEBSITE_DIRROOT.$this->dir.'/'.$this->name;
}

public function SetImgName($name) {
if (!empty($name)) {
$this->save = true; $this->name = $name;
}
}

public function ImportData($data=array()) {
empty($data) || is_array($data) && $this->data = $data;
}

private function GetMinSize() {
$fts_len = strlen((string)$this->unit) + 1;
$this->offset = imagefontwidth(2) * $fts_len;
$this->osSum = $this->offset + $this->space;
$this->omSum = $this->offset + $this->margin;
$this->xLen = $this->width - $this->osSum - $this->omSum;
$this->yLen = $this->height - $this->osSum - $this->omSum;

return $this->osSum + $this->omSum;
}

private function DrawCdtAxes() {
$min_size = $this->GetMinSize();
if ($this->width > $min_size && $this->height > $min_size) {
$this->image = @imagecreate($this->width, $this->height);
if ($this->image) {
$this->SetDftColor();

$cd_cr = imagecolorallocate($this->image, 0, 0, 0);
$cd_xs = $this->osSum; $cd_xe = $this->width - $this->offset;
$cd_ys = $this->offset; $cd_ye = $this->height - $this->osSum;

imageline($this->image, $cd_xs, $cd_ye, $cd_xe, $cd_ye, $cd_cr);
imageline($this->image, $cd_xs, $cd_ys, $cd_xs, $cd_ye, $cd_cr);
imageline($this->image, $cd_xe, $cd_ye, $cd_xe - 6, $cd_ye - 3, $cd_cr);
imageline($this->image, $cd_xe, $cd_ye, $cd_xe - 6, $cd_ye + 3, $cd_cr);
imageline($this->image, $cd_xs, $cd_ys, $cd_xs - 3, $cd_ys + 6, $cd_cr);
imageline($this->image, $cd_xs, $cd_ys, $cd_xs + 3, $cd_ys + 6, $cd_cr);
} else {
exit('画布建立失败!');
}
} else {
exit('画布尺寸设置不正确!');
}
}

private function DrawLattice() {
$this->SetDashLine();

$cdy_each = $this->unit;
$cdy_yMax = $this->mass * $cdy_each;
while ($cdy_yMax < max($this->data)) {
$cdy_each += $this->unit;
$cdy_yMax = $cdy_each * $this->mass;
} $this->unit = $cdy_each;
$cdx_beg = $this->osSum + 1;
$cdx_end = $this->width - $this->omSum;
$cdy_add = $this->yLen / $this->mass;

$cdy_beg = $this->omSum;
for ($i = 0; $i < $this->mass; $i ++) {
imageline($this->image, $cdx_beg, $cdy_beg, $cdx_end, $cdy_beg, IMG_COLOR_STYLED);

$fts_txt = (string)$this->unit * ($this->mass - $i);
$ftx_beg = $cdx_beg - $this->fontW * strlen($fts_txt) - $this->space;
$fty_beg = $cdy_beg - $this->fontH / 2;
imagestring($this->image, 2, $ftx_beg, $fty_beg, $fts_txt, $this->fontC);

$cdy_beg += $cdy_add;
}
}

private function SetDftColor() {
imagecolorallocate($this->image, $this->bgcor[0], $this->bgcor[1], $this->bgcor[2]);
}

private function GetRndColor() {
return imagecolorallocate($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));
}

private function SetDashLine() {
$cd_stop = imagecolorallocate($this->image, 255, 255, 255);
$cd_dash = imagecolorallocate($this->image, 200, 200, 200);
imagesetstyle($this->image, array($cd_stop, $cd_stop, $cd_stop,
$cd_dash, $cd_dash, $cd_dash));
$this->fontC = imagecolorallocate($this->image, 56, 56, 56);
}

private function Output() {
extract($this->GetImgSupot(), EXTR_OVERWRITE);

if ($this->save == false) {
header('Content-Type: '.$type);
$func($this->image);
} else {
if (empty($this->name)) {
$this->name = array_keys($this->data);
$this->name = md5(implode('', $this->name));
}
$this->dir = WEBSITE_DIRROOT.$this->dir;
$this->name = $this->name.'.'.$ext;
$func($this->image, $this->dir.'/'.$this->name);
}
}

private function GetImgSupot() {
$img_supt = imagetypes();
if (($img_supt & IMG_GIF) && function_exists('imagegif'))
return array('type'=>'image/gif', 'ext'=>'gif', 'func'=>'imagegif');
if (($img_supt & IMG_JPG) && function_exists('imagejpeg'))
return array('type'=>'image/jpeg', 'ext'=>'jpg', 'func'=>'imagejpeg');
if (($img_supt & IMG_PNG) && function_exists('imagepng'))
return array('type'=>'image/png', 'ext'=>'png', 'func'=>'imagepng');
}

function __destruct() {
image_destroy($this->image);
}
}

// 使用方法
$w = 640; $h = 480;
$info = array('春季'=>78, '夏季'=>65, '秋季'=>86, '冬季'=>55);
$draw_ins = new Draw($w, $h);
$draw_ins->ImportData($info);
// 柱状图
$draw_ins->DrawColumn();
// 线形图
// $draw_ins->DrawLine();
// 饼形图
// $draw_ins->DrawPie();
unset($draw_ins);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: