數據可視化是後台管理、報表系統的剛需。利用 PHP GD 库繪製扇形圖(餅圖)無需前端圖表庫,適合服務端渲染、郵件嵌入、API 直接輸出圖片等場景。本文提供一個可直接生產使用的封裝類,支持多數據系列、自定義顏色、圖例、標題等。
<?php
class PieChart {
private $width;
private $height;
private $diameter;
private $data = [];
private $colors = [];
private $labels = [];
private $title = '';
private $font = __DIR__ . '/fonts/DejaVuSans.ttf'; // 需準備 TTF 字體
public function __construct(int $diameter = 200) {
$this->diameter = $diameter;
$this->width = $this->height = $diameter + 40; // 留白
}
public function setData(array $values, array $labels = [], array $colors = []): self {
$this->data = array_values($values);
$this->labels = $labels ?: array_map(fn($i) => "項目 $i", array_keys($this->data));
$this->colors = $colors ?: $this->defaultColors(count($this->data));
return $this;
}
public function setTitle(string $title): self {
$this->title = $title;
return $this;
}
public function render(): void {
$total = array_sum($this->data);
if ($total === 0) return;
$img = imagecreatetruecolor($this->width, $this->height);
// 啟用抗鋸齒
imageantialias($img, true);
// 顏色分配
$white = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
$sliceColors = array_map(fn($c) => imagecolorallocate($img, ...$c), $this->colors);
// 背景
imagefill($img, 0, 0, $white);
$cx = $cy = $this->diameter / 2 + 20; // 圓心
$startDeg = -90; // 從 12 點鐘方向開始
foreach ($this->data as $i => $value) {
$endDeg = $startDeg + (360 * $value / $total);
$color = $sliceColors[$i];
// 繪製扇形填充(使用 imagefilledarc 更簡潔高效)
imagefilledarc($img, $cx, $cy, $this->diameter, $this->diameter, $startDeg, $endDeg, $color, IMG_ARC_PIE);
// 計算標籤位置(扇區中間角度)
$midDeg = deg2rad(($startDeg + $endDeg) / 2);
$labelX = $cx + cos($midDeg) * ($this->diameter * 0.65);
$labelY = $cy + sin($midDeg) * ($this->diameter * 0.65);
$percent = round(100 * $value / $total) . '%';
// 繪製百分比文字
if (file_exists($this->font)) {
imagettftext($img, 10, 0, $labelX - 15, $labelY + 5, $black, $this->font, $percent);
} else {
imagestring($img, 3, $labelX - 12, $labelY - 6, $percent, $black);
}
$startDeg = $endDeg;
}
// 繪製標題
if ($this->title && file_exists($this->font)) {
imagettftext($img, 14, 0, 20, 25, $black, $this->font, $this->title);
}
// 輸出
header('Content-Type: image/png');
imagepng($img);
imagedestroy($img);
}
private function defaultColors(int $n): array {
$base = [
[255, 99, 132], [54, 162, 235], [255, 206, 86],
[75, 192, 192], [153, 102, 255], [255, 159, 64],
[199, 199, 199], [83, 102, 255], [255, 99, 255],
];
return array_slice(array_merge($base, $base), 0, $n);
}
}
// 使用示例
$chart = new PieChart(300);
$chart->setData([30, 70, 45], ['華東', '華南', '華北'], [[255,0,0], [0,255,0], [0,0,255]])
->setTitle('2024 年各大區銷售佔比')
->render();
?>
| 函數 | 用途 |
|---|---|
imagecreatetruecolor() | 創建真彩色畫布,支持透明度與抗鋸齒 |
imagefilledarc(..., IMG_ARC_PIE) | 一步完成扇形繪製與填充,比手動 arc+line+fill 更高效 |
imagettftext() | 使用 TTF 字體繪製中文,需服務器安裝 freetype |
deg2rad() | 角度轉弧度,三角函數計算坐標必需 |
--with-freetype,且 TTF 字體文件可讀。imagepng($img, $filepath) 存盤。imagecolortransparent($img, $white) 設置透明色。IMG_ARC_EDGED。<img src="pie_chart.php?data=30,70,45&labels=華東,華南,華北&title=銷售佔比" alt="扇形圖">
將參數通過 GET 傳遞,即可實現動態圖表服務。
掌握 GD 繪圖,讓你的 PHP 應用具備原生圖表輸出能力,減少前端依賴,提升首屏渲染速度。