imagefill() 從中心點向外漫水。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 立體餅圖、側面陰影、底部圖例(色塊+標籤+數值+百分比)。
imagepng/imagewebp)。