利用php实现数据统计图

    年前由于工作需要,工作的中心由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);
   

转载于:https://www.cnblogs.com/cnzmm/archive/2011/03/20/1989262.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值