php中用GD繪制折線圖,代碼如下:
1 Class Chart{
2 private $image; // 定義圖像
3 private $title; // 定義標題
4 private $ydata; // 定義Y軸數據
5 private $xdata; // 定義X軸數據
6 private $seriesName; // 定義每個系列數據的名稱
7 private $color; // 定義條形圖顏色
8 private $bgcolor; // 定義圖片背景顏色
9 private $width; // 定義圖片的寬
10 private $height; // 定義圖片的長
11
12 /*
13 * 構造函數
14 * String title 圖片標題
15 * Array xdata 索引數組,X軸數據
16 * Array ydata 索引數組,數字數組,Y軸數據
17 * Array series_name 索引數組,數據系列名稱
18 */
19 function __construct($title,$xdata,$ydata,$seriesName) {
20 $this->title = $title;
21 $this->xdata = $xdata;
22 $this->ydata = $ydata;
23 $this->seriesName = $seriesName;
24 $this->color = array('#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4');
25 }
26
27 /*
28 * 公有方法,設置條形圖的顏色
29 * Array color 顏色數組,元素取值為'#058DC7'這種形式
30 */
31 function setBarColor($color){
32 $this->color = $color;
33 }
34 /*
35 * 繪制折線圖
36 */
37 public function paintLineChart() {
38 $ydataNum = $this->arrayNum($this->ydata); // 取得數據分組的個數
39 $max = $this->arrayMax($this->ydata); // 取得所有呈現數據的最大值
40 $max = ($max > 100)? $max : 100;
41 $multi = $max/100; // 如果最大數據是大於100的則進行縮小處理
42 $barHeightMulti = 2.2; // 條形高縮放的比例
43 $lineWidth = 50;
44 $chartLeft = (1+strlen($max))*12; // 設置圖片左邊的margin
45
46 $lineY = 250; // 初始化條形圖的Y的坐標
47 // 設置圖片的寬、高
48 //$this->width = $lineWidth*count($this->xdata) + $chartLeft - $lineWidth/1.6;
49
50 $margin = 10; // 小矩形描述右邊margin
51 $recWidth = 20; // 小矩形的寬
52 $recHeight = 15; // 小矩形的高
53 $space = 20; // 小矩形與條形圖的間距
54 $tmpWidth = 0;
55 // 設置圖片的寬、高
56 $lineChartWidth = $lineWidth*count($this->xdata) + $chartLeft - $lineWidth/1.6 ;
57 // 兩個系列數據以上的加上小矩形的寬
58 if($ydataNum > 1) {
59 $tmpWidth = $this->arrayLengthMax($this->seriesName)*10*4/3 + $space + $recWidth + + $margin;
60 }
61 $this->width = $lineChartWidth + $tmpWidth;
62
63 $this->height = 300;
64 $this->image = imagecreatetruecolor($this->width ,$this->height); // 准備畫布
65 $this->bgcolor = imagecolorallocate($this->image,255,255,255); // 圖片的背景顏色
66
67 // 設置條形圖的顏色
68 $color = array();
69 foreach($this->color as $col) {
70 $col = substr($col,1,strlen($col)-1);
71 $red = hexdec(substr($col,0,2));
72 $green = hexdec(substr($col,2,2));
73 $blue = hexdec(substr($col,4,2));
74 $color[] = imagecolorallocate($this->image ,$red, $green, $blue);
75 }
76
77 // 設置線段的顏色、字體的顏色、字體的路徑
78 $lineColor = imagecolorallocate($this->image ,0xcc,0xcc,0xcc);
79 $fontColor = imagecolorallocate($this->image, 0x95,0x8f,0x8f);
80 $fontPath = 'font/simsun.ttc';
81
82 imagefill($this->image,0,0,$this->bgcolor); // 繪畫背景
83
84 // 繪畫圖的分短線與左右邊線
85 for($i = 0; $i < 6; $i++ ) {
86 imageline($this->image,$chartLeft-10,$lineY-$barHeightMulti*$max/5/$multi*$i,$lineChartWidth,$lineY-$barHeightMulti*$max/5/$multi*$i,$lineColor);
87 imagestring($this->image,4,5,$lineY-$barHeightMulti*$max/5/$multi*$i-8,floor($max/5*$i),$fontColor);
88 }
89 imageline($this->image,$chartLeft-10,30,$chartLeft-10,$lineY,$lineColor);
90 imageline($this->image,$lineChartWidth-1,30,$lineChartWidth-1,$lineY,$lineColor);
91 $style = array($lineColor,$lineColor,$lineColor,$lineColor,$lineColor,$this->bgcolor,$this->bgcolor,$this->bgcolor,$this->bgcolor,$this->bgcolor);
92 imagesetstyle($this->image,$style);
93
94 // 繪制折線圖的分隔線(虛線)
95 foreach($this->xdata as $key => $val) {
96 $lineX = $chartLeft + 3 + $lineWidth*$key;
97 imageline($this->image,$lineX,30,$lineX,$lineY,IMG_COLOR_STYLED);
98 }
99
100 // 繪畫圖的折線
101 foreach($this->ydata as $key => $val) {
102 if($ydataNum == 1) {
103 // 一個系列數據時
104 if($key == count($this->ydata) - 1 ) break;
105 $lineX = $chartLeft + 3 + $lineWidth*$key;
106 $lineY2 = $lineY-$barHeightMulti*($this->ydata[$key+1])/$multi;
107
108 // 畫折線
109 if($key == count($this->ydata) - 2 ) {
110 imagefilledellipse($this->image,$lineX+$lineWidth,$lineY2,10,10,$color[0]);
111 }
112 imageline($this->image,$lineX,$lineY-$barHeightMulti*$val/$multi,$lineX+$lineWidth,$lineY2,$color[0]);
113 imagefilledellipse($this->image,$lineX,$lineY-$barHeightMulti*$val/$multi,10,10,$color[0]);
114 }elseif($ydataNum > 1) {
115 // 多個系列的數據時
116 foreach($val as $ckey => $cval) {
117
118 if($ckey == count($val) - 1 ) break;
119 $lineX = $chartLeft + 3 + $lineWidth*$ckey;
120 $lineY2 = $lineY-$barHeightMulti*($val[$ckey+1])/$multi;
121 // 畫折線
122 if($ckey == count($val) - 2 ) {
123 imagefilledellipse($this->image,$lineX+$lineWidth,$lineY2,10,10,$color[$key%count($this->color)]);
124 }
125 imageline($this->image,$lineX,$lineY-$barHeightMulti*$cval/$multi,$lineX+$lineWidth,$lineY2,$color[$key%count($this->color)]);
126 imagefilledellipse($this->image,$lineX,$lineY-$barHeightMulti*$cval/$multi,10,10,$color[$key%count($this->color)]);
127 }
128 }
129
130 }
131
132 // 繪畫條形圖的x坐標的值
133 foreach($this->xdata as $key => $val) {
134 $lineX = $chartLeft + $lineWidth*$key + $lineWidth/3 - 20;
135 imagettftext($this->image,10,-65,$lineX,$lineY+15,$fontColor,$fontPath,$this->xdata[$key]);
136 }
137
138 // 兩個系列數據以上時繪制小矩形及之後文字說明
139 if($ydataNum > 1) {
140 $x1 = $lineChartWidth + $space;
141 $y1 = 20 ;
142 foreach($this->seriesName as $key => $val) {
143 imagefilledrectangle($this->image,$x1,$y1,$x1+$recWidth,$y1+$recHeight,$color[$key%count($this->color)]);
144 imagettftext($this->image,10,0,$x1+$recWidth+5,$y1+$recHeight-2,$fontColor,$fontPath,$this->seriesName[$key]);
145 $y1 += $recHeight + 10;
146 }
147 }
148
149 // 繪畫標題
150 $titleStart = ($this->width - 5.5*strlen($this->title))/2;
151 imagettftext($this->image,11,0,$titleStart,20,$fontColor,$fontPath,$this->title);
152
153 // 輸出圖片
154 header("Content-Type:image/png");
155 imagepng ( $this->image );
156 }
157
158
159 /*
160 * 私有方法,當數組為二元數組時,統計數組的長度
161 * Array arr 要做統計的數組
162 */
163 private function arrayNum($arr) {
164 $num = 0;
165 if(is_array($arr)) {
166 $num++;
167 for($i = 0; $i < count($arr); $i++){
168 if(is_array($arr[$i])) {
169 $num = count($arr);
170 break;
171 }
172 }
173 }
174 return $num;
175 }
176
177 /*
178 * 私有方法,計算數組的深度
179 * Array arr 數組
180 */
181 private function arrayDepth($arr) {
182 $num = 0;
183 if(is_array($arr)) {
184 $num++;
185 for($i = 0; $i < count($arr); $i++){
186 if(is_array($arr[$i])) {
187 $num += $this->arrayDepth($arr[$i]);
188 break;
189 }
190 }
191 }
192 return $num;
193 }
194
195 /*
196 * 私有方法,找到一組中的最大值
197 * Array arr 數字數組
198 */
199 private function arrayMax($arr) {
200 $depth = $this->arrayDepth($arr);
201 $max = 0;
202 if($depth == 1) {
203 rsort($arr);
204 $max = $arr[0];
205 }elseif($depth > 1) {
206 foreach($arr as $val) {
207 if(is_array($val)) {
208 if($this->arrayMax($val) > $max) {
209 $max = $this->arrayMax($val);
210 }
211 }else{
212 if($val > $max){
213 $max = $val;
214 }
215 }
216 }
217 }
218 return $max;
219 }
220
221 /*
222 * 私有方法,求數組的平均值
223 * Array arr 數字數組
224 */
225 function arrayAver($arr) {
226 $aver = array();
227 foreach($arr as $val) {
228 if(is_array($val)) {
229 $aver = array_merge($aver,$val);
230 }else{
231 $aver[] = $val;
232 }
233 }
234 return array_sum($aver)/count($aver);
235 }
236
237 /*
238 * 私有方法,求數組中元素長度最大的值
239 * Array arr 字符串數組,必須是漢字
240 */
241 private function arrayLengthMax($arr) {
242 $length = 0;
243 foreach($arr as $val) {
244 $length = strlen($val) > $length ? strlen($val) : $length;
245 }
246 return $length/3;
247 }
248
249 // 析構函數
250 function __destruct(){
251 imagedestroy($this->image);
252 }
253 }
測試代碼如下:
1 $xdata = array('測試一','測試二','測試三','測試四','測試五','測試六','測試七','測試八','測試九');
2 $ydata = array(array(29,30,45,54,65,45,76,23,54),array(89,60,90,23,35,45,56,23,56));
3 $color = array();
4 $seriesName = array("七月","八月");
5 $title = "測試數據";
6 $Img = new Chart($title,$xdata,$ydata,$seriesName);
7 $Img->paintLineChart();
效果圖如下: