免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1734 | 回复: 0
打印 上一主题 下一主题

利用php实现数据统计图 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-03-20 14:39 |只看该作者 |倒序浏览
转:web freer

利用php实现数据统计图


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

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

  2. 002        /*  

  3. 003            * class: 数据统计图  

  4. 004            * author: 51JS.COM-ZMM  

  5. 005            * date: 2011.2.1  

  6. 006            * email: 304924248@qq.com  

  7. 007            * blog: http://www.cnblogs.com/cnzmm/  

  8. 008        */

  9. 009   

  10. 010        class Draw {  

  11. 011              public $mass=10, $unit=10, $data=array(), $save=false, $dir='/images/count';  

  12. 012              private $width=0, $height=0, $side=0, $bgcor=array(255, 255, 255);  

  13. 013              private $name, $image, $offset=0, $margin=20, $space=3, $font='/fonts/simsun.ttc';  

  14. 014              private $fontW, $fontH, $fontC, $fontA, $osSum, $omSum, $xLen, $yLen, $size=9;  

  15. 015   

  16. 016              function __construct($width=0, $height=0, $data=array()) {  

  17. 017                  $this->width = $width;   

  18. 018                  $this->height = $height;  

  19. 019                  if (!empty($data)) $this->data = $data;  

  20. 020   

  21. 021                  $this->fontW = imagefontwidth(2);  

  22. 022                  $this->fontH = imagefontheight(2);  

  23. 023                  $this->fontA = imagefontheight($this->size);  

  24. 024                  $this->fontA = round($this->fontA / 2) + 2;  

  25. 025   

  26. 026                  $this->font = WEBSITE_DIRROOT.$this->font;  

  27. 027                  if (!is_file($this->font)) {  

  28. 028                      exit('字体文件不存在!');  

  29. 029                  } else {   

  30. 030                      $this->font = realpath($this->font);  

  31. 031                  }  

  32. 032              }  

  33. 033   

  34. 034              public function DrawPie($name="") {  

  35. 035                  $this->SetImgName($name);  

  36. 036   

  37. 037                  $this->side = $this->width;  

  38. 038                  if ($this->side > 0 && !empty($this->data)) {  

  39. 039                      $pie_core = $this->side / 2;  

  40. 040   

  41. 041                      $fts_max = 0;  

  42. 042                      foreach (array_keys($this->data) as $item) {  

  43. 043                          $chk_itm = $item.' '.max($this->data).' 00.00%';  

  44. 044                          $fts_box = imagettfbbox($this->size, 0, $this->font, $chk_itm);  

  45. 045                          $chk_len = $fts_box[4] - $fts_box[6];  

  46. 046                          if ($chk_len > $fts_max) $fts_max = $chk_len;  

  47. 047                      } $pie_cAdd = 48 + $fts_max;   

  48. 048   

  49. 049                      $this->image = @imagecreate($this->side + $pie_cAdd, $this->side + 1);   

  50. 050                      if ($this->image) {  

  51. 051                          $this->SetDftColor();  

  52. 052   

  53. 053                          $dat_sum = array_sum($this->data);  

  54. 054                          $arc_beg = array(-180, -90, 0, 90, 180);  

  55. 055                          $arc_beg = $arc_beg[array_rand($arc_beg)];  

  56. 056   

  57. 057                          $fts_add = $this->fontA * 2;  

  58. 058                          $ftx_beg = $this->side + 28; $fty_beg = 2;  

  59. 059                          $ftx_add = 20; $fty_add = 20;  

  60. 060                          $fts_cor = imagecolorallocate($this->image, 0, 0, 0);  

  61. 061                          $fty_chk = $fty_add * count($this->data);  

  62. 062                          while ($fty_chk > $this->side + 2) {  

  63. 063                                 $fty_chk = --$fty_add * count($this->data);  

  64. 064                          }  

  65. 065   

  66. 066                          foreach ($this->data as $item => $data) {  

  67. 067                               $rnd_cor = $this->GetRndColor();   

  68. 068                               $arc_pct = number_format($data * 100 / $dat_sum, 2);  

  69. 069                               $arc_end = $data * 360 / $dat_sum + $arc_beg;  

  70. 070                               $item = iconv('gb2312', 'UTF-8', (string)$item);  

  71. 071   

  72. 072                               imagefilledarc($this->image, $pie_core, $pie_core, $this->side, $this->side, $arc_beg, $arc_end, $rnd_cor, IMG_ARC_PIE);  

  73. 073                               imagefilledrectangle($this->image, $ftx_beg, $fty_beg, $ftx_beg + 12, $fty_beg + 10, $rnd_cor);  

  74. 074                               imagettftext($this->image, $this->size, 0, $ftx_beg + $ftx_add, $fty_beg + $this->fontA, $fts_cor, $this->font, $item.' '.$data.' '.$arc_pct.'%');  

  75. 075   

  76. 076                               $fty_beg += $fty_add; $arc_beg = $arc_end;   

  77. 077                          }   

  78. 078   

  79. 079                          $this->Output();  

  80. 080                      }  

  81. 081                  } else {  

  82. 082                      exit('画布边长设置不正确或统计数据为空!');  

  83. 083                  }  

  84. 084              }  

  85. 085   

  86. 086              public function DrawColumn($name="") {  

  87. 087                  $this->SetImgName($name);  

  88. 088   

  89. 089                  if (!empty($this->data)) {  

  90. 090                      $this->DrawCdtAxes();  

  91. 091                      $this->DrawLattice();  

  92. 092   

  93. 093                      $cdx_cut = count($this->data);  

  94. 094                      $cdx_add = floor($this->xLen / $cdx_cut);   

  95. 095                      $cdy_add = $this->yLen / $this->mass;  

  96. 096                      imagesetthickness($this->image, floor($cdx_add / 2));  

  97. 097   

  98. 098                      $cdy_end = $this->height - $this->osSum - 1;  

  99. 099                      $cdx_beg = floor($cdx_add / 2) + $this->osSum;  

  100. 100                      foreach ($this->data as $item => $data) {  

  101. 101                           $cdy_beg = $this->yLen - ($data * $cdy_add / $this->unit) + $this->omSum;  

  102. 102                           imageline($this->image, $cdx_beg, $cdy_beg, $cdx_beg, $cdy_end, $this->GetRndColor());  

  103. 103   

  104. 104                           $fts_txt = (string)$data;  

  105. 105                           $ftx_beg = $cdx_beg - $this->fontW * strlen($fts_txt) / 2;  

  106. 106                           $fty_beg = $cdy_beg - $this->fontH - $this->space;  

  107. 107                           imagestring($this->image, 2, $ftx_beg, $fty_beg, $fts_txt, $this->fontC);  

  108. 108   

  109. 109                           $fts_txt = iconv('gb2312', 'UTF-8', (string)$item);  

  110. 110                           $fts_box = imagettfbbox($this->size, 0, $this->font, $fts_txt);  

  111. 111                           $ftx_beg = $cdx_beg - floor($fts_box[4] - $fts_box[6]) / 2;  

  112. 112                           $fty_beg = $this->height - $this->offset + $this->fontA;   

  113. 113                           imagettftext($this->image, $this->size, 0, $ftx_beg, $fty_beg, $this->fontC, $this->font, $fts_txt);  

  114. 114   

  115. 115                           $cdx_beg += $cdx_add;  

  116. 116                      }  

  117. 117                     

  118. 118                      $this->Output();  

  119. 119                  } else {  

  120. 120                      exit('统计数据为空!');  

  121. 121                  }  

  122. 122              }  

  123. 123   

  124. 124              public function DrawLine($name="") {  

  125. 125                  $this->SetImgName($name);  

  126. 126   

  127. 127                  if (!empty($this->data)) {  

  128. 128                      $this->DrawCdtAxes();  

  129. 129                      $this->DrawLattice();  

  130. 130   

  131. 131                      $dat_idx = 0;  

  132. 132                      $cd_line = imagecolorallocate($this->image, 255, 0, 0);  

  133. 133                      $cd_fold = imagecolorallocate($this->image, 0, 0, 255);  

  134. 134   

  135. 135                      $cdx_cut = count($this->data) - 1;  

  136. 136                      $cdx_add = floor($this->xLen / $cdx_cut);   

  137. 137                      $cdy_add = $this->yLen / $this->mass;  

  138. 138     

  139. 139                      $cdx_old = 0; $cdx_beg = $this->osSum;  

  140. 140                      $cdy_old = 0; $cdy_beg = $this->omSum - 5;   

  141. 141                      $cdy_end = $this->height - $this->osSum - 1;   

  142. 142                      foreach ($this->data as $item => $data) {  

  143. 143                           imagesetthickness($this->image, 1);  

  144. 144                           $dat_idx > 0 && imageline($this->image, $cdx_beg, $cdy_beg, $cdx_beg, $cdy_end, IMG_COLOR_STYLED);  

  145. 145                           imagesetthickness($this->image, 2);  

  146. 146   

  147. 147                           $cdx_dot = $cdx_beg;  

  148. 148                           $cdy_dot = $this->yLen - $data * $cdy_add / $this->unit + $this->omSum;  

  149. 149                           if ($cdx_old > 0 && $cdy_old > 0) {   

  150. 150                               imageline($this->image, $cdx_old, $cdy_old, $cdx_dot, $cdy_dot, $cd_line);  

  151. 151                               imagefilledellipse($this->image, $cdx_old, $cdy_old, 6, 6, $cd_fold);  

  152. 152                           }   

  153. 153                           imagefilledellipse($this->image, $cdx_dot, $cdy_dot, 6, 6, $cd_fold);  

  154. 154   

  155. 155                           $fts_txt = '('.(string)$data.')';  

  156. 156                           if ($dat_idx == 0) {  

  157. 157                               $ftx_beg = $cdx_dot + $this->space + 3;  

  158. 158                               $fty_beg = $cdy_dot - $this->fontH / 2;  

  159. 159                           } else {  

  160. 160                               $ftx_beg = $cdx_dot - $this->fontW * strlen($fts_txt) / 2;  

  161. 161                               $fty_beg = $cdy_dot - $this->fontH - $this->space * 2;  

  162. 162                           }  

  163. 163                           imagestring($this->image, 2, $ftx_beg, $fty_beg, $fts_txt, $this->fontC);  

  164. 164                              

  165. 165                           $fts_txt = iconv('gb2312', 'UTF-8', (string)$item);  

  166. 166                           $fts_box = imagettfbbox($this->size, 0, $this->font, $fts_txt);  

  167. 167                           $ftx_beg = $cdx_beg - floor($fts_box[4] - $fts_box[6]) / 2;  

  168. 168                           $fty_beg = $this->height - $this->offset + $this->fontA;  

  169. 169                           imagettftext($this->image, $this->size, 0, $ftx_beg, $fty_beg, $this->fontC, $this->font, $fts_txt);  

  170. 170   

  171. 171                           $dat_idx ++; $cdx_beg += $cdx_add;   

  172. 172                           $cdx_old = $cdx_dot; $cdy_old = $cdy_dot;   

  173. 173                      }   

  174. 174   

  175. 175                      $this->Output();  

  176. 176                  } else {  

  177. 177                      exit('统计数据为空!');  

  178. 178                  }  

  179. 179              }  

  180. 180   

  181. 181              public function GetImgName() {  

  182. 182                  return empty($this->name) ? null :   

  183. 183                         WEBSITE_DIRROOT.$this->dir.'/'.$this->name;  

  184. 184              }  

  185. 185   

  186. 186              public function SetImgName($name) {  

  187. 187                  if (!empty($name)) {   

  188. 188                      $this->save = true; $this->name = $name;  

  189. 189                  }  

  190. 190              }  

  191. 191   

  192. 192              public function ImportData($data=array()) {  

  193. 193                  empty($data) || is_array($data) && $this->data = $data;  

  194. 194              }  

  195. 195   

  196. 196              private function GetMinSize() {  

  197. 197                  $fts_len = strlen((string)$this->unit) + 1;  

  198. 198                  $this->offset = imagefontwidth(2) * $fts_len;   

  199. 199                  $this->osSum = $this->offset + $this->space;  

  200. 200                  $this->omSum = $this->offset + $this->margin;  

  201. 201                  $this->xLen = $this->width - $this->osSum - $this->omSum;  

  202. 202                  $this->yLen = $this->height - $this->osSum - $this->omSum;  

  203. 203   

  204. 204                  return $this->osSum + $this->omSum;  

  205. 205              }  

  206. 206   

  207. 207              private function DrawCdtAxes() {  

  208. 208                  $min_size = $this->GetMinSize();  

  209. 209                  if ($this->width > $min_size && $this->height > $min_size) {  

  210. 210                      $this->image = @imagecreate($this->width, $this->height);  

  211. 211                      if ($this->image) {  

  212. 212                          $this->SetDftColor();  

  213. 213   

  214. 214                          $cd_cr = imagecolorallocate($this->image, 0, 0, 0);  

  215. 215                          $cd_xs = $this->osSum; $cd_xe = $this->width - $this->offset;   

  216. 216                          $cd_ys = $this->offset; $cd_ye = $this->height - $this->osSum;  

  217. 217   

  218. 218                          imageline($this->image, $cd_xs, $cd_ye, $cd_xe, $cd_ye, $cd_cr);  

  219. 219                          imageline($this->image, $cd_xs, $cd_ys, $cd_xs, $cd_ye, $cd_cr);  

  220. 220                          imageline($this->image, $cd_xe, $cd_ye, $cd_xe - 6, $cd_ye - 3, $cd_cr);  

  221. 221                          imageline($this->image, $cd_xe, $cd_ye, $cd_xe - 6, $cd_ye + 3, $cd_cr);  

  222. 222                          imageline($this->image, $cd_xs, $cd_ys, $cd_xs - 3, $cd_ys + 6, $cd_cr);  

  223. 223                          imageline($this->image, $cd_xs, $cd_ys, $cd_xs + 3, $cd_ys + 6, $cd_cr);  

  224. 224                      } else {  

  225. 225                          exit('画布建立失败!');  

  226. 226                      }  

  227. 227                  } else {  

  228. 228                      exit('画布尺寸设置不正确!');  

  229. 229                  }  

  230. 230              }  

  231. 231   

  232. 232              private function DrawLattice() {  

  233. 233                  $this->SetDashLine();  

  234. 234   

  235. 235                  $cdy_each = $this->unit;  

  236. 236                  $cdy_yMax = $this->mass * $cdy_each;  

  237. 237                  while ($cdy_yMax < max($this->data)) {   

  238. 238                         $cdy_each += $this->unit;   

  239. 239                         $cdy_yMax = $cdy_each * $this->mass;  

  240. 240                  } $this->unit = $cdy_each;  

  241. 241                  $cdx_beg = $this->osSum + 1;   

  242. 242                  $cdx_end = $this->width - $this->omSum;   

  243. 243                  $cdy_add = $this->yLen / $this->mass;   

  244. 244   

  245. 245                  $cdy_beg = $this->omSum;  

  246. 246                  for ($i = 0; $i < $this->mass; $i ++) {  

  247. 247                       imageline($this->image, $cdx_beg, $cdy_beg, $cdx_end, $cdy_beg, IMG_COLOR_STYLED);  

  248. 248   

  249. 249                       $fts_txt = (string)$this->unit * ($this->mass - $i);  

  250. 250                       $ftx_beg = $cdx_beg - $this->fontW * strlen($fts_txt) - $this->space;  

  251. 251                       $fty_beg = $cdy_beg - $this->fontH / 2;  

  252. 252                       imagestring($this->image, 2, $ftx_beg, $fty_beg, $fts_txt, $this->fontC);  

  253. 253   

  254. 254                       $cdy_beg += $cdy_add;  

  255. 255                  }  

  256. 256              }  

  257. 257   

  258. 258              private function SetDftColor() {  

  259. 259                  imagecolorallocate($this->image, $this->bgcor[0], $this->bgcor[1], $this->bgcor[2]);  

  260. 260              }  

  261. 261   

  262. 262              private function GetRndColor() {  

  263. 263                  return imagecolorallocate($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255));  

  264. 264              }  

  265. 265   

  266. 266              private function SetDashLine() {  

  267. 267                  $cd_stop = imagecolorallocate($this->image, 255, 255, 255);  

  268. 268                  $cd_dash = imagecolorallocate($this->image, 200, 200, 200);  

  269. 269                  imagesetstyle($this->image, array($cd_stop, $cd_stop, $cd_stop,   

  270. 270                                                    $cd_dash, $cd_dash, $cd_dash));  

  271. 271                  $this->fontC = imagecolorallocate($this->image, 56, 56, 56);  

  272. 272              }  

  273. 273   

  274. 274              private function Output() {  

  275. 275                  extract($this->GetImgSupot(), EXTR_OVERWRITE);  

  276. 276   

  277. 277                  if ($this->save == false) {  

  278. 278                      header('Content-Type: '.$type);  

  279. 279                      $func($this->image);  

  280. 280                  } else {  

  281. 281                      if (empty($this->name)) {  

  282. 282                          $this->name = array_keys($this->data);  

  283. 283                          $this->name = md5(implode('', $this->name));  

  284. 284                      }  

  285. 285                      $this->dir = WEBSITE_DIRROOT.$this->dir;  

  286. 286                      $this->name = $this->name.'.'.$ext;  

  287. 287                      $func($this->image, $this->dir.'/'.$this->name);  

  288. 288                  }   

  289. 289              }  

  290. 290   

  291. 291              private function GetImgSupot() {  

  292. 292                  $img_supt = imagetypes();  

  293. 293                  if (($img_supt & IMG_GIF) && function_exists('imagegif'))  

  294. 294                      return array('type'=>'image/gif', 'ext'=>'gif', 'func'=>'imagegif');  

  295. 295                  if (($img_supt & IMG_JPG) && function_exists('imagejpeg'))   

  296. 296                      return array('type'=>'image/jpeg', 'ext'=>'jpg', 'func'=>'imagejpeg');  

  297. 297                  if (($img_supt & IMG_PNG) && function_exists('imagepng'))  

  298. 298                      return array('type'=>'image/png', 'ext'=>'png', 'func'=>'imagepng');  

  299. 299              }  

  300. 300   

  301. 301              function __destruct() {  

  302. 302                  image_destroy($this->image);  

  303. 303              }  

  304. 304        }  

  305. 305   

  306. 306        // 使用方法  

  307. 307        $w = 640; $h = 480;  

  308. 308        $info = array('春季'=>78, '夏季'=>65, '秋季'=>86, '冬季'=>55);   

  309. 309        $draw_ins = new Draw($w, $h);  

  310. 310        $draw_ins->ImportData($info);  

  311. 311        // 柱状图  

  312. 312        $draw_ins->DrawColumn();  

  313. 313        // 线形图  

  314. 314        // $draw_ins->DrawLine();  

  315. 315        // 饼形图  

  316. 316        // $draw_ins->DrawPie();  

  317. 317        unset($draw_ins);  
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP