当前位置:中国站长下载文章中心网页编程PHP编程 → 使用 PHP 5.0创建图形的巧妙方法

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

减小字体 增大字体 作者:编辑整理  来源:互联网  发布时间:2008-9-15 22:05:26
本文将展示如何使用PHP构建面向对象的图形层。使用面向对象的系统可以用来构建复杂的图形,这比使用标准PHP库中所提供的基本功能来构建图形简单很多。

我将图形编辑程序分为两类:一类是绘图程序,利用这种程序可以一个像素一个像素地绘制图像;另外一类是制图程序,这种程序提供了一组对象,例如线、椭圆和矩形,您可以使用这些对象来组合成一幅大图像,例如JPEG。绘图程序非常适合进行像素级的控制。但是对于业务图形来说,制图程序是比较好的方式,因为大部分图形都是由矩形、线和椭圆组成的。

PHP内置的制图基本操作与绘图程序非常类似。它们对于绘制图像来说功能非常强大;但是如果您希望自己的图像是一组对象集合时,这就不太适合了。本文将向您展示如何在PHP图形库的基础上构建一个面向对象的图形库。您将使用PHPV5中提供的面向对象的扩展。

具有面向对象的图形支持之后,您的图形代码就非常容易理解和维护了。您可能还需要从一种单一的图形源将图形合成为多种类型的媒介: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.基本的图形库

<?phpclassGraphicsEnvironment{public$width;public$height;public$gdo;public$colors=array();publicfunction__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"));}publicfunctionwidth(){return$this->width;}publicfunctionheight(){return$this->height;}publicfunctionaddColor($name,$r,$g,$b){$this->colors[$name]=imagecolorallocate($this->gdo,$r,$g,$b);}publicfunctiongetGraphicObject(){return$this->gdo;}publicfunctiongetColor($name){return$this->colors[$name];}publicfunctionsaveAsPng($filename){imagepng($this->gdo,$filename);}}abstractclassGraphicsObject{abstractpublicfunctionrender($ge);}classLineextendsGraphicsObject{private$color;private$sx;private$sy;private$ex;private$ey;publicfunction__construct($color,$sx,$sy,$ex,$ey){$this->color=$color;$this->sx=$sx;$this->sy=$sy;$this->ex=$ex;$this->ey=$ey;}publicfunctionrender($ge){imageline($ge->getGraphicObject(),$this->sx,$this->sy,$this->ex,$this->ey,$ge->getColor($this->color));}}?>

测试代码如清单2所示:

清单2.基本图形库的测试代码

<?phprequire_once("glib.php");$ge=newGraphicsEnvironment(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[]=newLine("black",10,5,100,200);$gobjs[]=newLine("blue",200,150,390,380);$gobjs[]=newLine("red",60,40,10,300);$gobjs[]=newLine("green",5,390,390,10);foreach($gobjsas$gobj){$gobj->render($ge);}$ge->saveAsPng("test.png");?>

这个测试程序创建了一个图形环境。然后创建几条线,它们指向不同的方向,具有不同的颜色。然后,render方法可以将它们画到图形平面上。最后,这段代码将这个图像保存为test.png。

在本文中,都是使用下面的命令行解释程序来运行这段代码,如下所示:

%phptest.php%


图2显示了所生成的test.png文件在Firefox中的样子。

图2.简单的图形对象测试



这当然不如蒙娜丽莎漂亮,但是可以满足目前的工作需要。

添加维数

我们的第一个需求——提供图形对象的能力——已经满足了,现在应该开始满足第二个需求了:可以使用一个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信息的图形库

<?phpclassGraphicsEnvironment{public$width;public$height;public$gdo;public$colors=array();publicfunction__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"));}publicfunctionwidth(){return$this->width;}publicfunctionheight(){return$this->height;}publicfunctionaddColor($name,$r,$g,$b){$this->colors[$name]=imagecolorallocate($this->gdo,$r,$g,$b);}publicfunctiongetGraphicObject(){return$this->gdo;}publicfunctiongetColor($name){return$this->colors[$name];}publicfunctionsaveAsPng($filename){imagepng($this->gdo,$filename);}}abstractclassGraphicsObject{abstractpublicfunctionrender($ge);abstractpublicfunctionz();}abstractclassBoxObjectextendsGraphicsObject{protected$color;protected$sx;protected$sy;protected$ex;protected$ey;protected$z;publicfunction__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;}publicfunctionz(){return$this->z;}}classLineextendsBoxObject{publicfunctionrender($ge){imageline($ge->getGraphicObject(),$this->sx,$this->sy,$this->ex,$this->ey,$ge->getColor($this->color));}}classRectangleextendsBoxObject{publicfunctionrender($ge){imagefilledrectangle($ge->getGraphicObject(),$this->sx,$this->sy,$this->ex,$this->ey,$ge->getColor($this->color));}}classOvalextendsBoxObject{publicfunctionrender($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));}}?>

[1] [2] [3]  下一页