使用 PHP GD 擴充模組,透過多層疊加方式繪製具有 3D 厚度視覺效果的圓餅圖,適合簡易統計報表展示。
<?php
/**
* 3D 圓餅圖生成器
* @author deepblue
* @date 2009-05-26
*/
// 1. 建立 200x200 真彩色畫布
$image = imagecreatetruecolor(200, 200);
// 2. 分配顏色
$colors = [
'red' => imagecolorallocate($image, 255, 0, 0),
'blue' => imagecolorallocate($image, 0, 0, 255),
'yellow' => imagecolorallocate($image, 255, 255, 0),
'violet' => imagecolorallocate($image, 255, 0, 255),
'white' => imagecolorallocate($image, 255, 255, 255),
'black' => imagecolorallocate($image, 0, 0, 0),
];
// 3. 繪製 3D 底層(厚度 20 像素,從 y=120 遞減至 y=101)
for ($y = 120; $y > 100; $y--) {
imagefilledarc($image, 100, $y, 200, 120, 0, 30, $colors['red'], IMG_ARC_PIE);
imagefilledarc($image, 100, $y, 200, 120, 30, 80, $colors['blue'], IMG_ARC_PIE);
imagefilledarc($image, 100, $y, 200, 120, 80, 360, $colors['yellow'], IMG_ARC_PIE);
}
// 4. 繪製頂層(y=100)與外框
imagearc($image, 100, 100, 200, 120, 0, 360, $colors['black']); // 外框
imagefilledarc($image, 100, 100, 200, 120, 0, 30, $colors['red'], IMG_ARC_PIE);
imagefilledarc($image, 100, 100, 200, 120, 30, 80, $colors['blue'], IMG_ARC_PIE);
imagefilledarc($image, 100, 100, 200, 120, 80, 360, $colors['yellow'], IMG_ARC_PIE);
// 5. 繪製百分比文字(需 TrueType 字型檔)
$text = '36%';
// 若需顯示中文,需轉碼:iconv('gbk', 'UTF-8', '佔用:30%')
$fontFile = 'simhei.ttf'; // 需確保字型檔存在於腳本目錄
imagettftext($image, 10, 345, 170, 115, $colors['white'], $fontFile, $text);
// 6. 輸出與釋放
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
?>
bool imagefilledarc(
resource $image,
int $cx, int $cy, // 圓心座標
int $w, int $h, // 寬、高(橢圓)
int $start, int $end, // 起始/結束角度(度,0=3點鐘方向,順時針)
int $color, // 顏色識別碼
int $style // 模式常數組合
)
常用模式常數:
IMG_ARC_PIE:扇形(連接圓心)IMG_ARC_CHORD:弦形(連接弧端點)IMG_ARC_NOFILL:僅繪製輪廓IMG_ARC_EDGED:連接圓心與弧端點(配合 NOFILL 畫邊框)利用 垂直位移疊加:將同一扇形在 Y 軸上連續繪製多層(本例 20 層),形成視覺上的厚度。頂層再疊加一次並加上黑色外框,強化立體感。
<?php
function draw3DPieChart(array $data, array $colors, $width = 400, $height = 300) {
$image = imagecreatetruecolor($width, $height);
$allocated = [];
foreach ($colors as $name => $rgb) {
$allocated[$name] = imagecolorallocate($image, $rgb[0], $rgb[1], $rgb[2]);
}
$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);
$total = array_sum($data);
$startAngle = 0;
$cx = $width / 2;
$cy = $height / 2 + 20; // 略微下移預留頂部空間
$w = $width * 0.8;
$h = $height * 0.6;
$depth = 20;
// 計算每段角度
$segments = [];
foreach ($data as $label => $value) {
$angle = 360 * $value / $total;
$segments[] = ['label' => $label, 'value' => $value, 'angle' => $angle, 'color' => $colors[array_key_first($colors)]];
// 實際應用中需循環分配顏色
}
// 繪製底層(略,邏輯同前)
// 繪製頂層與文字標籤(需計算標籤座標,避免重疊)
return $image;
}
?>
| 問題 | 解決方案 |
|---|---|
| 圖片輸出為空白/錯誤 | 確認 GD 擴充已啟用(phpinfo() 檢查);腳本前無任何輸出(含空白、BOM) |
| 中文顯示亂碼/方塊 | 使用 imagettftext() 搭配 TrueType 字型(如 simhei.ttf、msjh.ttc);確認字型檔路徑正確 |
| 3D 效果不明顯 | 增加 $depth 值;調整底層顏色較深、頂層較亮 |
| 記憶體耗盡 | 大尺寸圖片需調整 memory_limit;用完即 imagedestroy() |
pChart、PHPChart、GdGraph 封裝更完善。SVG 或 PDF 產生可無限縮放的圖表。本範例展示 GD 底層繪圖原理,適合學習圖形學基礎或極簡環境部署;實際專案建議採用前端圖表庫分擔伺服器負載。