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

PHP GD imageline 繪製直線完整指南:參數詳解、線型控制與進階幾何應用

     編輯:PHP 綜合知識

前言

直線是幾何繪圖的最小單元。PHP GD 的 imageline() 函數雖參數簡單,但掌握其座標系、顏色分配、線型樣式 (虛線/點線/粗線) 及組合幾何邏輯,是繪製坐標系、折線圖、幾何圖形、網格、連接線等所有線條類視覺元件的基礎。本文將從基礎參數到進階線型模擬、抗鋸齒策略全方位講解。

函數簽名與參數幾何定義

bool imageline (
    resource $image,
    int $x1, int $y1,   // 起點座標
    int $x2, int $y2,   // 終點座標
    int $color          // 線條顏色 (imagecolorallocate 返回)
);

GD 座標系鐵律 (必背)

  • 原點 (0,0):圖片**左上角**
  • X 軸:向右為正
  • Y 軸:向下為正 (關鍵!與數學座標系 Y 向上相反)
  • 像素包含:線條包含**起點與終點像素**。畫 (0,0) 到 (9,0) 寬度為 10 像素。

基礎代碼範例

<?php
$im = imagecreatetruecolor(400, 300);
$white = imagecolorallocate($im, 255,255,255);
$black = imagecolorallocate($im, 0,0,0);
$red = imagecolorallocate($im, 255,0,0);
$blue = imagecolorallocate($im, 0,0,255);
imagefill($im, 0, 0, $white);

// 1. 基本直線:左上(30,30) 到 右下(370,270)
imageline($im, 30, 30, 370, 270, $red);

// 2. 水平線:Y固定
imageline($im, 50, 150, 350, 150, $blue);

// 3. 垂直線:X固定
imageline($im, 200, 50, 200, 250, $blue);

// 4. 對角線 (45度) - 視覺上因像素比例可能不呈現標準45度
imageline($im, 100, 100, 300, 300, $black); // 實際超出畫布

header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
?>

進階線型控制:GD 原生不支援虛線/粗線,需手動實現

1. 粗線模擬 (多平行線疊加)

function imageline_thick($im, $x1, $y1, $x2, $y2, $color, $thickness = 3) {
    if ($thickness <= 1) return imageline($im, $x1, $y1, $x2, $y2, $color);
    
    // 計算垂直於線條的單位向量 (dx, dy)
    $dx = $x2 - $x1;
    $dy = $y2 - $y1;
    $len = sqrt($dx*$dx + $dy*$dy);
    if ($len == 0) return;
    
    // 單位法向量 (垂直於線段)
    $nx = -$dy / $len;
    $ny = $dx / $len;
    
    $half = ($thickness - 1) / 2;
    for ($i = -$half; $i <= $half; $i++) {
        $offsetX = $nx * $i;
        $offsetY = $ny * $i;
        imageline($im, 
            $x1 + $offsetX, $y1 + $offsetY, 
            $x2 + $offsetX, $y2 + $offsetY, 
            $color
        );
    }
}

2. 虛線/點線模擬 (Bresenham 算法改良版)

function imageline_dashed($im, $x1, $y1, $x2, $y2, $color, $dashLen = 10, $gapLen = 5) {
    $dx = abs($x2 - $x1);
    $dy = abs($y2 - $y1);
    $sx = ($x1 < $x2) ? 1 : -1;
    $sy = ($y1 < $y2) ? 1 : -1;
    $err = $dx - $dy;
    $len = 0; // 當前虛線段長度
    $draw = true; // 是否繪製像素
    
    while (true) {
        if ($draw) imagesetpixel($im, $x1, $y1, $color);
        
        $len++;
        if ($draw && $len >= $dashLen) { $draw = false; $len = 0; }
        elseif (!$draw && $len >= $gapLen) { $draw = true; $len = 0; }
        
        if ($x1 === $x2 && $y1 === $y2) break;
        $e2 = 2 * $err;
        if ($e2 > -$dy) { $err -= $dy; $x1 += $sx; }
        if ($e2 < $dx) { $err += $dx; $y1 += $sy; }
    }
}

3. 箭頭線 (帶箭頭的有向線段)

function imageline_arrow($im, $x1, $y1, $x2, $y2, $color, $arrowSize = 10, $arrowAngle = 30) {
    imageline($im, $x1, $y1, $x2, $y2, $color); // 主線
    
    $angle = atan2($y1 - $y2, $x2 - $x1); // 線段角度 (注意 Y 軸反轉)
    $arrowAngleRad = deg2rad($arrowAngle);
    
    // 箭頭兩翼終點
    $x3 = $x2 + $arrowSize * cos($angle + $arrowAngleRad);
    $y3 = $y2 - $arrowSize * sin($angle + $arrowAngleRad); // Y反轉
    $x4 = $x2 + $arrowSize * cos($angle - $arrowAngleRad);
    $y4 = $y2 - $arrowSize * sin($angle - $arrowAngleRad);
    
    imageline($im, $x2, $y2, $x3, $y3, $color);
    imageline($im, $x2, $y2, $x4, $y4, $color);
    // 可選:填滿箭頭三角形
    // imagefilledpolygon($im, [$x2,$y2, $x3,$y3, $x4,$y4], 3, $color);
}

抗鋸齒與畫質優化

方法原理優點缺點
imageantialias($im, true)GD 內建抗鋸齒 (僅支援真彩色、線條/多邊形)零成本開啟效果有限,僅邊緣像素混合,不支援粗線/虛線
超採樣 (2x/4x 縮放)大畫布繪製 → imagescale($im, $w/2, $h/2, IMG_BICUBIC)效果最佳,接近向量級記憶體/CPU 成倍增長
ImageMagick (Imagick)專業圖形庫,真正向量渲染完美抗鋸齒、粗線、虛線、漸變線需安裝擴展,部署較複雜
前端 Canvas/SVG瀏覽器原生向量繪圖零後端負擔、互動動畫、完美畫質需前端實現,無法直接生成圖片下載

實戰幾何應用場景

1. 折線圖 / 走勢圖 核心邏輯

function drawLineChart($data, $width=600, $height=400, $padding=50) {
    $im = imagecreatetruecolor($width, $height);
    imageantialias($im, true);
    $white = imagecolorallocate($im, 255,255,255);
    $grid = imagecolorallocate($im, 230,230,230);
    $axis = imagecolorallocate($im, 100,100,100);
    $line = imagecolorallocate($im, 52, 152, 219);
    imagefill($im, 0, 0, $white);
    
    $maxVal = max($data); $minVal = min($data);
    $range = $maxVal - $minVal ?: 1;
    $count = count($data);
    $stepX = ($width - 2*$padding) / max(1, $count-1);
    
    // 畫網格與座標軸 ...
    
    // 畫折線
    for ($i = 0; $i < $count-1; $i++) {
        $x1 = $padding + $i * $stepX;
        $y1 = $height - $padding - (($data[$i] - $minVal) / $range) * ($height - 2*$padding);
        $x2 = $padding + ($i+1) * $stepX;
        $y2 = $height - $padding - (($data[$i+1] - $minVal) / $range) * ($height - 2*$padding);
        imageline($im, $x1, $y1, $x2, $y2, $line);
    }
    return $im;
}

2. 正多邊形生成器 (幾何計算 + 連線)

function drawPolygon($im, $cx, $cy, $radius, $sides, $color, $rotation = -90) {
    $points = [];
    for ($i = 0; $i < $sides; $i++) {
        $angle = deg2rad($rotation + $i * 360 / $sides);
        $points[] = $cx + $radius * cos($angle);
        $points[] = $cy + $radius * sin($angle); // GD Y向下,sin 正常
    }
    // 使用 imagepolygon (自動閉合) 或 imageline 迴圈
    imagepolygon($im, $points, $sides, $color); // 空心
    // imagefilledpolygon($im, $points, $sides, $color); // 實心
}

3. 等距網格 / 圖紙背景

function drawGrid($im, $step = 20, $color = 0xEEEEEE, $majorStep = 100, $majorColor = 0xDDDDDD) {
    $w = imagesx($im); $h = imagesy($im);
    // 垂直線
    for ($x = 0; $x <= $w; $x += $step) {
        $c = ($x % $majorStep === 0) ? $majorColor : $color;
        imageline($im, $x, 0, $x, $h, $c);
    }
    // 水平線
    for ($y = 0; $y <= $h; $y += $step) {
        $c = ($y % $majorStep === 0) ? $majorColor : $color;
        imageline($im, 0, $y, $w, $y, $c);
    }
}

常見錯誤排查表

  1. 線條不顯示:顏色分配失敗 (返回 false)、座標超出畫布範圍 (GD 會靜默截斷)、起點終點相同 (長度 0)。
  2. 座標系搞反:Y 軸向下為正。數學函數 sin/cos 配合 GD 時,Y 分量**不取反** (因為數學 Y 向上,GD Y 向下,sin 正好抵消)。但 atan2($dy, $dx) 計算角度時,$dy = $y1 - $y2 (目標 - 起點,補償 Y 反轉)。
  3. 虛線/粗線函數無效:GD 無原生支援,必須用上文自定義函數或改用 Imagick。
  4. 線條鋸齒嚴重:開啟 imageantialias($im, true);大尺度場景採用超採樣縮放。
  5. 透明線條失效:需 imagealphablending(true) + imagesavealpha(true) + imagecolorallocatealpha(..., alpha)。

總結

imageline() 是 GD 繪圖的**幾何原子**。核心掌握點:

  1. 座標系:左上原點,Y 向下。
  2. 顏色:真彩色模式下無限色 + Alpha。
  3. 缺失功能自補:粗線 (法向位移疊加)、虛線 (Bresenham 狀態機)、箭頭 (三角函數)、抗鋸齒 (超採樣/Imagick)。
  4. 組合威力:折線圖、多邊形、網格、座標系、幾何圖形、連接流程圖,皆由 imageline 迴圈組合而成。

若專案對線條畫質、樣式豐富度、效能有高要求,**強烈建議遷移至 ImageMagick (Imagick 擴展) 或前端 Canvas/SVG**。GD 適合簡單、低併發、無複雜線型需求的圖片生成場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved