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();
效果圖如下: