PHP 5.0建立圖形的實用方法完整篇第1/3頁

來源:互聯網
上載者:User

本文將展示如何使用 PHP 構建物件導向的圖形層。使用物件導向的系統可以用來構建複雜的圖形,這比使用標準 PHP 庫中所提供的準系統來構建圖形簡單很多。

  我將圖形編輯程式分為兩類:一類是繪圖程式,利用這種程式可以一個像素一個像素地繪製映像;另外一類是製圖程式,這種程式提供了一組對象,例如線、橢圓和矩形,您可以使用這些對象來組合成一幅大映像,例如 JPEG。繪圖程式非常適合進行像素級的控制。但是對於業務圖形來說,製圖程式是比較好的方式,因為大部分圖形都是由矩形、線和橢圓組成的。

  PHP 內建的製圖基本操作與繪圖程式非常類似。它們對於繪製映像來說功能非常強大;但是如果您希望自己的映像是一組對象集合時,這就不太適合了。本文將向您展示如何在 PHP 圖形庫的基礎上構建一個物件導向的圖形庫。您將使用 PHP V5 中提供的物件導向的擴充。

  具有物件導向的圖形支援之後,您的圖形代碼就非常容易理解和維護了。您可能還需要從一種單一的圖形源將圖形合成為多種類型的媒介:Flash 電影、SVG 等等。

  目標

  建立一個繪圖物件庫包括 3 個主要的目標:

  從基本操作切換到對象上

  它不使用 imageline、imagefilledrectangle 以及其他圖形函數,這個庫應該提供一些對象,例如 Line、Rectangle 和 Oval,它們可以用來製作映像。它應該還可以支援構建更大的複雜物件或對對象進行分組的功能。

  可以進行 z 值排序

  製圖程式讓畫家可以在畫面表面上上下移動繪圖物件。這個庫應該可以支援將一個對象放到其他對象前後的功能:它使用了一個 z 值,用來定義對象從製圖平面開始的高度。z 值越大的對象被畫得越晚,也就出現在那些 z 值較小的對象之上。

  提供 viewport 的轉換

  通常,資料的座標空間與映像的座標空間是不同的。PHP 中的圖形基本操作是對映像的座標平面進行操作的。這個圖形庫應該支援 viewport 的規範,這樣您就可以在一個程式員熟悉的座標系統中指定圖形了,並且可以自動進行伸縮來適應任何映像的大小。

  由於這裡有很多特性,您將一步步地編寫代碼來展示這些代碼如何不斷增加功能。

  基礎知識

  讓我們首先來看一個圖形環境對象和一個名為 GraphicsObject 的介面,它是使用一個 Line 類實現的,功能就是用來畫線。UML 1 所示。

圖 1. 圖形環境和繪圖物件介面

  GraphicsEnvironment 類中儲存了繪圖物件和一組顏色,還包括寬度和高度。saveAsPng 方法負責將當前的映像輸出到指定的檔案中。

  GraphicsObject 是任何繪圖物件都必須使用的介面。要開始使用這個介面,您所需要做的就是使用 render 方法來畫這個對象。它是由一個 Line 類實現的,它利用 4 個座標:開始和結束的 x 值,開始和結束的 y 值。它還有一個顏色。當調用 render 時,這個對象從 sx,sy 到 ex,ey 畫一條由名字指定的顏色的線。

  這個庫的代碼如清單 1 所示。

  清單 1. 基本的圖形庫

 <?php class GraphicsEnvironment {  public $width;  public $height;  public $gdo;  public $colors = array();  public function __construct( $width, $height )  {  $this->width = $width;  $this->height = $height;  $this->gdo = imagecreatetruecolor( $width, $height );  $this->addColor( "white", 255, 255, 255 );  imagefilledrectangle( $this->gdo, 0, 0,   $width, $height,   $this->getColor( "white" ) );  }  public function width() { return $this->width; }  public function height() { return $this->height; }  public function addColor( $name, $r, $g, $b )  {  $this->colors[ $name ] = imagecolorallocate(   $this->gdo,   $r, $g, $b );  }  public function getGraphicObject()  {  return $this->gdo;  }  public function getColor( $name )  {  return $this->colors[ $name ];  }  public function saveAsPng( $filename )  {  imagepng( $this->gdo, $filename );  } } abstract class GraphicsObject {  abstract public function render( $ge ); } class Line extends GraphicsObject {  private $color;  private $sx;  private $sy;  private $ex;  private $ey;  public function __construct( $color, $sx, $sy, $ex, $ey )  {  $this->color = $color;  $this->sx = $sx;  $this->sy = $sy;  $this->ex = $ex;  $this->ey = $ey;  }  public function render( $ge )  {  imageline( $ge->getGraphicObject(),   $this->sx, $this->sy,   $this->ex, $this->ey,   $ge->getColor( $this->color ) );  } } ?> 

  測試代碼如清單 2 所示:

  清單 2. 基本圖形庫的測試代碼

 <?php require_once( "glib.php" ); $ge = new GraphicsEnvironment( 400, 400 ); $ge->addColor( "black", 0, 0, 0 ); $ge->addColor( "red", 255, 0, 0 ); $ge->addColor( "green", 0, 255, 0 ); $ge->addColor( "blue", 0, 0, 255 ); $gobjs = array(); $gobjs []= new Line( "black", 10, 5, 100, 200 ); $gobjs []= new Line( "blue", 200, 150, 390, 380 ); $gobjs []= new Line( "red", 60, 40, 10, 300 ); $gobjs []= new Line( "green", 5, 390, 390, 10 ); foreach( $gobjs as $gobj ) { $gobj->render( $ge ); } $ge->saveAsPng( "test.png" ); ?> 

  這個測試程式建立了一個圖形環境。然後建立幾條線,它們指向不同的方向,具有不同的顏色。然後,render 方法可以將它們畫到圖形平面上。最後,這段代碼將這個映像儲存為 test.png。

  在本文中,都是使用下面的命令列解釋程式來運行這段代碼,如下所示:

 % php test.php % 

  圖 2 顯示了所產生的 test.png 檔案在 Firefox 中的樣子。

  圖2. 簡單的繪圖物件測試

  這當然不如蒙娜麗莎漂亮,但是可以滿足目前的工作需要。

[NextPage]

添加維數

  我們的第一個需求 —— 提供繪圖物件的能力 —— 已經滿足了,現在應該開始滿足第二個需求了:可以使用一個 z 值將一個對象放到其他對象的上面或下面。

  我們可以將每個 z 值當作是原始映像的一個面。所畫的元素是按照 z 值從最小到最大的順序來畫的。例如,讓我們畫兩個圖形元素:一個紅色的圓和一個黑色的方框。圓的 z 值是 100,而黑方框的 z 值是 200。這樣會將圓放到方框之後, 3 所示:

  圖3. 不同 z 值的面

  我們只需要修改一下 z 值就可以將這個紅圓放到黑方框之上。要實現這種功能,我們需要讓每個 GraphicsObject 都具有一個 z() 方法,它返回一個數字,就是 z 值。由於您需要建立不同的繪圖物件(Line、Oval 和 Rectangle),您還需要建立一個基本的類 BoxObject,其他 3 個類都使用它來維護起點和終點的座標、z 值和這個對象的顏色(請參看圖 4)。

  圖 4. 給系統添加另外一維:z 值

  這個圖形庫的新代碼如清單 3 所示:

  清單 3. 可以處理 z 資訊的圖形庫

 <?php class GraphicsEnvironment {  public $width;  public $height;  public $gdo;  public $colors = array();  public function __construct( $width, $height )  {  $this->width = $width;  $this->height = $height;  $this->gdo = imagecreatetruecolor( $width, $height );  $this->addColor( "white", 255, 255, 255 );  imagefilledrectangle( $this->gdo, 0, 0,   $width, $height,   $this->getColor( "white" ) );  }  public function width() { return $this->width; }  public function height() { return $this->height; }  public function addColor( $name, $r, $g, $b )  {  $this->colors[ $name ] = imagecolorallocate(   $this->gdo,   $r, $g, $b );  }  public function getGraphicObject()  {  return $this->gdo;  }  public function getColor( $name )  {  return $this->colors[ $name ];  }  public function saveAsPng( $filename )  {  imagepng( $this->gdo, $filename );  } } abstract class GraphicsObject {  abstract public function render( $ge );  abstract public function z(); } abstract class BoxObject extends GraphicsObject {  protected $color;  protected $sx;  protected $sy;  protected $ex;  protected $ey;  protected $z;  public function __construct( $z, $color, $sx, $sy, $ex, $ey )  {  $this->z = $z;  $this->color = $color;  $this->sx = $sx;  $this->sy = $sy;  $this->ex = $ex;  $this->ey = $ey;  }  public function z() { return $this->z; } } class Line extends BoxObject {  public function render( $ge )  {  imageline( $ge->getGraphicObject(),   $this->sx, $this->sy,   $this->ex, $this->ey,   $ge->getColor( $this->color ) );  } } class Rectangle extends BoxObject {  public function render( $ge )  {  imagefilledrectangle( $ge->getGraphicObject(),   $this->sx, $this->sy,   $this->ex, $this->ey,   $ge->getColor( $this->color ) );  } } class Oval extends BoxObject {  public function render( $ge )  {  $w = $this->ex - $this->sx;  $h = $this->ey - $this->sy;  imagefilledellipse( $ge->getGraphicObject(),   $this->sx + ( $w / 2 ),   $this->sy + ( $h / 2 ),   $w, $h,   $ge->getColor( $this->color ) );  } } ?> 

  測試代碼也需要進行更新,如清單 4 所示。

  清單 4. 更新後的測試代碼

 <?php require_once( "glib.php" ); function zsort( $a, $b ) {  if ( $a->z() < $b->z() ) return -1;  if ( $a->z() > $b->z() ) return 1;  return 0; } $ge = new GraphicsEnvironment( 400, 400 ); $ge->addColor( "black", 0, 0, 0 ); $ge->addColor( "red", 255, 0, 0 ); $ge->addColor( "green", 0, 255, 0 ); $ge->addColor( "blue", 0, 0, 255 ); $gobjs = array(); $gobjs []= new Oval( 100, "red", 50, 50, 150, 150 ); $gobjs []= new Rectangle( 200, "black", 100, 100, 300, 300 ); usort( $gobjs, "zsort" ); foreach( $gobjs as $gobj ) { $gobj->render( $ge ); } $ge->saveAsPng( "test.png" ); ?> 

  此處需要注意兩件事情。首先是我們添加了建立 Oval 和 Rectangle 對象的過程,其中第一個參數是 z 值。其次是調用了 usort,它使用了 zsort 函數來對繪圖物件根據 z 值進行排序。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.