首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 手繪 3D 立體餅圖:無依賴、純 GD 實現

     編輯:PHP 綜合知識

核心思路

  1. 用橢圓弧模擬 3D 圓餅側面(高度 $v)。
  2. 扇面填色用 imagefill() 從中心點向外漫水。
  3. 側面顏色取表面色暗化(RGB 各除 2)。
  4. 標籤區在圖表下方繪製色塊 + 文字 + 百分比。

關鍵函數簽名

chx_sector3d($img, $ox,$oy, $a,$b, $v, $sd,$ed, $color)
// $ox,$oy 圓心,$a,$b 橢圓長短軸,$v 高度,$sd/$ed 起止角度(度)

完整可運行代碼(整理版)

<?php
// ---- pie3dfun.php ----
define('ANGLE_STEP', 5);

function chx_getDark($img,$clr) {
    $rgb = imagecolorsforindex($img,$clr);
    return [$rgb['red']>>1, $rgb['green']>>1, $rgb['blue']>>1];
}
function chx_ellipsePt($a,$b,$deg) {
    $rad = deg2rad($deg);
    return [round($a*cos($rad)), round($b*sin($rad))];
}
function chx_arc($img,$ox,$oy,$a,$b,$sd,$ed,$clr) {
    $n = ceil(($ed-$sd)/ANGLE_STEP);
    [$x0,$y0] = chx_ellipsePt($a,$b,$sd);
    for($i=0;$i<$n;$i++) {
        $d = min($ed, $sd+ANGLE_STEP*($i+1));
        [$x,$y] = chx_ellipsePt($a,$b,$d);
        imageline($img,$ox+$x0,$oy+$y0,$ox+$x,$oy+$y,$clr);
        [$x0,$y0] = [$x,$y];
    }
}
function chx_sector($img,$ox,$oy,$a,$b,$sd,$ed,$clr) {
    $n = ceil(($ed-$sd)/ANGLE_STEP);
    [$x0,$y0] = chx_ellipsePt($a,$b,$sd);
    imageline($img,$ox+$x0,$oy+$y0,$ox,$oy,$clr);
    for($i=0;$i<$n;$i++) {
        $d = min($ed, $sd+ANGLE_STEP*($i+1));
        [$x,$y] = chx_ellipsePt($a,$b,$d);
        imageline($img,$ox+$x0,$oy+$y0,$ox+$x,$oy+$y,$clr);
        [$x0,$y0] = [$x,$y];
    }
    imageline($img,$ox+$x0,$oy+$y0,$ox,$oy,$clr);
    [$cx,$cy] = chx_ellipsePt($a/2,$b/2,($sd+$ed)/2);
    imagefill($img,$ox+$cx,$oy+$cy,$clr);
}
function chx_sector3d($img,$ox,$oy,$a,$b,$v,$sd,$ed,$clr) {
    chx_sector($img,$ox,$oy,$a,$b,$sd,$ed,$clr);
    if($sd < 180) {
        $ed = min($ed, 180);
        [$r,$g,$b] = chx_getDark($img,$clr);
        $dark = imagecolorallocate($img,$r,$g,$b);
        [$sx,$sy] = chx_ellipsePt($a,$b,$sd);
        [$ex,$ey] = chx_ellipsePt($a,$b,$ed);
        imageline($img,$ox+$sx,$oy+$sy,$ox+$sx,$oy+$sy+$v,$dark);
        imageline($img,$ox+$ex,$oy+$ey,$ox+$ex,$oy+$ey+$v,$dark);
        chx_arc($img,$ox,$oy+$v,$a,$b,$sd,$ed,$dark);
        [$mx,$my] = chx_ellipsePt($a,$b,($sd+$ed)/2);
        imagefill($img,$ox+$mx,$oy+$my+$v/2,$dark);
    }
}

// ---- pie3d.php ----
require 'pie3dfun.php';

$data  = [30,10,20,20,10,20,10,20];
$labels= ['a1','a2','a3','a4','a5','a6','a7','a8'];
$colors= [0x99ff00,0xff6666,0x0099ff,0xff99ff,0xffff99,0x99ffff,0xff3333,0x009999];

$a=150; $b=50; $v=20; $font=5;
$ox=$a+5; $oy=$b+5;
$fw=imagefontwidth($font); $fh=imagefontheight($font);

$w = $a*2+10;
$h = $b*2+$v+10 + ($fh+2)*count($data);
$img = imagecreate($w,$h);

$clrIdx = [];
foreach($colors as $c) $clrIdx[] = imagecolorallocate($img,$c>>16,($c>>8)&0xFF,$c&0xFF);
$white = imagecolorallocate($img,255,255,255);
$black = imagecolorallocate($img,0,0,0);
imagefill($img,0,0,$white);

$total = array_sum($data);
$sd = 0;
$ly = $b*2+$v+10;
foreach($data as $i=>$val) {
    $ed = $sd + $val/$total*360;
    chx_sector3d($img,$ox,$oy,$a,$b,$v,$sd,$ed,$clrIdx[$i]);
    // 圖例
    imagefilledrectangle($img,5,$ly,5+$fw,$ly+$fh,$clrIdx[$i]);
    imagerectangle($img,5,$ly,5+$fw,$ly+$fh,$black);
    imagestring($img,$font,5+2*$fw,$ly,
        "{$labels[$i]}:$val (".round($val/$total*10000)/100 ."%)",$black);
    $ly += $fh+2;
    $sd = $ed;
}

header('Content-Type: image/gif');
imagegif($img);
imagedestroy($img);

效果預覽

生成 320x? GIF,含 3D 立體餅圖、側面陰影、底部圖例(色塊+標籤+數值+百分比)。

擴展方向

  • 支援圖片輸出 PNG/WebP(imagepng/imagewebp)。
  • 加入標題、圖例位置配置、動畫生成(逐幀 GIF)。
  • 對接 Chart.js / ECharts 前端渲染,後端僅供數據 API。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved