科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件使用 PHP 5.0创建图形的巧妙方法

使用 PHP 5.0创建图形的巧妙方法

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文将展示如何使用 PHP 构建面向对象的图形层

作者:Jack Herrington 来源:ibm 2007年10月21日

关键字: Linux

  • 评论
  • 分享微博
  • 分享邮件
添加维数

  我们的第一个需求 —— 提供图形对象的能力 —— 已经满足了,现在应该开始满足第二个需求了:可以使用一个 z 值将一个对象放到其他对象的上面或下面。

  我们可以将每个 z 值当作是原始图像的一个面。所画的元素是按照 z 值从最小到最大的顺序来画的。例如,让我们画两个图形元素:一个红色的圆和一个黑色的方框。圆的 z 值是 100,而黑方框的 z 值是 200。这样会将圆放到方框之后,如图 3 所示:

  图3. 不同 z 值的面

不同 z 值的面

  我们只需要修改一下 z 值就可以将这个红圆放到黑方框之上。要实现这种功能,我们需要让每个 GraphicsObject 都具有一个 z() 方法,它返回一个数字,就是 z 值。由于您需要创建不同的图形对象(Line、Oval 和 Rectangle),您还需要创建一个基本的类 BoxObject,其他 3 个类都使用它来维护起点和终点的坐标、z 值和这个对象的颜色(请参看图 4)。

  图 4. 给系统添加另外一维:z 值
给系统添加另外一维: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 值进行排序。

  在运行这个程序时,test.png 文件应该如图 5 所示。

  图5. 红圆在黑方框之后

红圆在黑方框之后

  现在修改下面的代码:

 
$gobjs []= new Oval( 200, "red", 50, 50, 150, 150 ); 
$gobjs []= new Rectangle( 100, "black", 100, 100, 300, 300 ); 

  再次运行这个代码,突然这个椭圆就在这个方框上面了,如图 6 所示。

  图6. 红圆现在在黑方框上面了

红圆现在在黑方框上面了

  红圆现在就出现在黑方框上面了,尽管它是先创建的,也是首先添加到数组中的。这就是 z 值的实际价值:您可以按照任何顺序来创建对象,并可以通过调整每个对象的 z 值来调整彼此之间的相对位置。

  在这段代码中,z 值排序是在这个库之外实现的。让我们通过创建一个新容器对象 Group 来实现这种功能,其中保存了一组 GraphicsObject 对象。Group 对象然后再处理排序的问题。

  Group 类的代码如清单 5 所示。

  清单 5. Group 类

 
function zsort( $a, $b ) 
{ 
  if ( $a->z() < $b->z() ) return -1; 
  if ( $a->z() > $b->z() ) return 1; 
  return 0; 
} 

class Group extends GraphicsObject 
{ 
  private $z; 
  protected $members = array(); 
  public function __construct( $z ) 
  { 
    $this->z = $z; 
  } 
  public function add( $member ) 
  { 
    $this->members []= $member; 
  } 
  public function render( $ge ) 
  { 
    usort( $this->members, "zsort" ); 
    foreach( $this->members as $gobj ) 
    { 
      $gobj->render( $ge ); 
    } 
  } 
  public function z() { return $this->z; } 
} 

  Group 对象的任务是保持一个对象数组,然后在画图时,逐个对对象zo进行排序和画图。

  更新后的测试代码如清单 6 所示。

  清单 6. 更新后的测试代码

 
<?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 ); 

$g1 = new Group( 0 ); 
$g1->add( new Oval( 200, "red", 50, 50, 150, 150 ) );   
$g1->add( new Rectangle( 100, "black", 100, 100, 300, 300 ) ); 

$g1->render( $ge ); 

$ge->saveAsPng( "test.png" ); 
?> 

  现在所有的客户机需要做的是创建一个 Group 对象。它会处理排序和其他操作。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章