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

PHP 繪製中文圓形印章特效(兩種實作方式)

     編輯:PHP 相關知識

PHP 繪製中文圓形印章特效(兩種實作方式)

利用 GD 函式庫動態產生圓形印章圖片,包含外框、內圓、環繞文字與五角星。本文提供兩種實作:物件導向類別與程式碼直寫版,皆支援自訂文字、半徑、字體、顏色等參數。

方式一:circleSeal 類別(物件導向)

封裝所有繪圖邏輯,建構子可傳入印章文字、半徑、邊框寬度、五角星半徑、傾斜角度、字體大小、內圓半徑等參數。核心步驟:

  1. createImg():建立真彩色畫布,設定透明背景與紅色筆刷
  2. drawRim():以多層 imagearc 疊加形成粗邊框
  3. drawInnerCircle():繪製內圓
  4. drawString():將文字拆字,依角度平均分佈於圓周,使用 imagettftext 繪製 TrueType 字體
  5. drawStart():計算五角星頂點與內凹點座標,以 imagefilledpolygon 填滿
  6. outPut():輸出 PNG 並銷毀資源
<?php
class circleSeal {
    private $sealString, $strMaxLeng=12, $sealRadius, $rimWidth, $innerRadius;
    private $startRadius, $startAngle, $charAngle, $centerDot;
    private $img, $font, $fontSize, $width, $height, $points, $charRadius, $spacing=1;
    private $backGround;

    public function __construct($str='', $rad=75, $rmwidth=6, $strad=24, $stang=0, $crang=0, $fsize=16, $inrad=0) {
        $this->sealString = empty($str) ? '印章測試字符串' : $str;
        $this->sealRadius = $rad; $this->rimWidth = $rmwidth;
        $this->startRadius = $strad; $this->startAngle = $stang;
        $this->charAngle = $crang; $this->innerRadius = $inrad;
        $this->centerDot = array('x'=>$rad, 'y'=>$rad);
        $this->font = __DIR__ . '/simkai.ttf'; // 需自備楷體字體檔
        $this->fontSize = $fsize;
    }

    private function createImg() {
        $this->width = $this->height = 2 * $this->sealRadius;
        $this->img = imagecreate($this->width, $this->height);
        imagecolorresolvealpha($this->img, 255,255,255,127); // 透明背景
        $this->backGround = imagecolorallocate($this->img, 255,0,0); // 紅色
    }

    private function drawRim() {
        for ($i=0; $i<$this->rimWidth; $i++) {
            imagearc($this->img, $this->centerDot['x'], $this->centerDot['y'],
                $this->width-$i, $this->height-$i, 0, 360, $this->backGround);
        }
    }

    private function drawInnerCircle() {
        if ($this->innerRadius > 0) {
            imagearc($this->img, $this->centerDot['x'], $this->centerDot['y'],
                2*$this->innerRadius, 2*$this->innerRadius, 0, 360, $this->backGround);
        }
    }

    private function drawString() {
        // 編碼轉 UTF-8
        $charset = mb_detect_encoding($this->sealString);
        if ($charset != 'UTF-8') $this->sealString = mb_convert_encoding($this->sealString, 'UTF-8', 'GBK');

        $this->charRadius = $this->sealRadius - $this->rimWidth - $this->fontSize;
        $len = mb_strlen($this->sealString, 'utf8');
        if ($len > $this->strMaxLeng) $len = $this->strMaxLeng;
        $avgAngle = 360 / $this->strMaxLeng;

        for ($i=0; $i<$len; $i++) {
            $ch = mb_substr($this->sealString, $i, 1, 'utf8');
            $r = 630 + $this->charAngle + $avgAngle*($i - $len/2) + $this->spacing*($i-1);
            $R = 720 - $this->charAngle + $avgAngle*($len-2*$i-1)/2 + $this->spacing*(1-$i);
            $x = $this->centerDot['x'] + $this->charRadius * cos(deg2rad($r));
            $y = $this->centerDot['y'] + $this->charRadius * sin(deg2rad($r));
            imagettftext($this->img, $this->fontSize, $R, $x, $y, $this->backGround, $this->font, $ch);
        }
    }

    private function drawStart() {
        $ang_out = 18 + $this->startAngle;
        $ang_in  = 56 + $this->startAngle;
        $rad_out = $this->startRadius;
        $rad_in  = $rad_out * 0.382;
        $this->points = array();
        for ($i=0; $i<5; $i++) {
            $this->points[] = $rad_out * cos(2*M_PI/5*$i - deg2rad($ang_out)) + $this->centerDot['x'];
            $this->points[] = $rad_out * sin(2*M_PI/5*$i - deg2rad($ang_out)) + $this->centerDot['y'];
            $this->points[] = $rad_in * cos(2*M_PI/5*($i+1) - deg2rad($ang_in)) + $this->centerDot['x'];
            $this->points[] = $rad_in * sin(2*M_PI/5*($i+1) - deg2rad($ang_in)) + $this->centerDot['y'];
        }
        imagefilledpolygon($this->img, $this->points, 10, $this->backGround);
    }

    private function outPut() {
        header('Content-type:image/png');
        imagepng($this->img);
        imagedestroy($this->img);
    }

    public function doImg() {
        $this->createImg();
        $this->drawRim();
        $this->drawInnerCircle();
        $this->drawString();
        $this->drawStart();
        $this->outPut();
    }
}

// 使用範例
// $seal = new circleSeal('你我他坐站走東西南北中', 75, 6, 24, 0, 0, 16, 40);
// $seal->doImg();
?>

方式二:單一腳本直寫版(適合快速嵌入)

透過 $_GET['hos'] 接收文字參數,直接輸出印章圖片。邏輯與類別版相似,但將計算寫在流程中,適合不需複用的場合。

<?php
$hos = isset($_GET['hos']) ? iconv('GBK', 'UTF-8', $_GET['hos']) : '';
if (!$hos) exit;

$im = imagecreate(150,150);
$gray = imagecolorresolvealpha($im,200,200,200,127);
$red  = imagecolorallocate($im,230,150,150);
for ($i=0; $i<6; $i++) imagearc($im,75,75,148-$i,148-$i,0,360,$red);

$font = 'C:/Windows/Fonts/simkai.ttf'; // 請依伺服器環境調整路徑
$size = 30;
imagettftext($im,$size,0,72-$size/2,72+$size/2,$red,$font,'★');

$a=75; $b=-75; $r=65; $m=40; $size=16;
$r -= $size;
$word = array();
$max = 18;
$count = mb_strlen($hos,'utf8');
if ($count > $max) $count = $max;
if ($count > 12) $m = floor(360/$count);
elseif ($count > 5) $m -= $count;

for ($i=0; $i<$count; $i++) $word[] = mb_substr($hos,$i,1,'utf8');
$j = floor($count/2);

if ($j != $count/2) { // 奇數字
    for ($i=$j; $i>=0; $i--) {
        $arc = $m*($j-$i) + $size/2;
        $x = round($r*cos((90+$arc)*M_PI/180)) + $a;
        $y = -1*(round($r*sin((90+$arc)*M_PI/180)) + $b);
        if ($arc < 10) $arc = 0;
        imagettftext($im,$size,$arc,$x,$y,$red,$font,$word[$i]);

        $arc = $m*($j-$i) - $size/2;
        $x = round($r*cos((90-$arc)*M_PI/180)) + $a;
        $y = -1*(round($r*sin((90-$arc)*M_PI/180)) + $b);
        if ($arc < 10) $arc = 0;
        imagettftext($im,$size,-$arc,$x,$y,$red,$font,$word[$j+$j-$i]);
    }
} else { // 偶數字
    $j--;
    for ($i=$j; $i>=0; $i--) {
        $arc = $m/2 + $m*($j-$i) + $size/2;
        $x = round($r*cos((90+$arc)*M_PI/180)) + $a;
        $y = -1*(round($r*sin((90+$arc)*M_PI/180)) + $b);
        imagettftext($im,$size,$arc,$x,$y,$red,$font,$word[$i]);

        $arc = $m/2 + $m*($j-$i) - $size/2;
        $x = round($r*cos((90-$arc)*M_PI/180)) + $a;
        $y = -1*(round($r*sin((90-$arc)*M_PI/180)) + $b);
        imagettftext($im,$size,-$arc,$x,$y,$red,$font,$word[$j+$j+1-$i]);
    }
}
header('Content-Type:image/png');
imagepng($im);
?>

部署提醒

  • 需確認伺服器安裝 php-gd 且支援 FreeType(imagettftext)。
  • 字體檔 simkai.ttf(楷體)需自行放置於可讀取路徑,或改用其他 TrueType 字體。
  • 輸出前請勿有任何輸出(含空白、BOM),否則 PNG 會損壞。
  • 若需儲存檔案而非直接輸出,將 imagepng($im) 改為 imagepng($im, 'filename.png')。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved