线形图形 为了开始,我们可以创建一个空的200x200像素的画布,并填充为灰色。在这上面可以绘制我们的线段。 我们可以为每个办公室分配一个颜色,红色代表伦敦,兰色代表亚特兰大。 现在可以开始取出数据并把它画出来了。需要牢记的一件重要的事就是在画线的时候,ImageLine 要求 我们告诉它开始处的x和y坐标还有线的结束坐标。现在如果从一个数据库中抓出数据,将一次只能得到一组 坐标。所以可以或者将数据存储在数组中,或使用一个临时变量来保存前一组坐标。我选择了使用数组。 除了将要绘制的实际坐标之外,还需要知道可达到的最大值(图形的顶部)还有信息列的数目(沿着x轴要 画的点的个数)。所以在与数据库连接之后,从数据库中选出了MAX(g_num) 值并将其保存起来为后面使用。 然后选出所以g_team等于'London'的所有记录,并得到返回的记录行数,所以我们将知道有多少要处理的数 据列数。从前面的表格中,你可以看到我们将处理6个月或列数据,并且最大值为410。 <?php $columns = 6; $max = 410; ?> x值总是最容易处理的 -- 它的范围从0到图像的宽度,此处为200。我们将在0处理开始画线并希望在200 结束,所以在以$x=0开始之后,将需要增加$x值直到$columns-1次(此处为5)以达到200 -- 这样我们要画 6次,最后一次将在200处。记住这点以后我们可以创建一个名为$xincrement的变量,并赋给它200除以 ($columns-1)的值。然后将给出$x一个开始值0 并且在每一次循环的底部,当从结果集中抓取记录行时,我 们可以给$x增加$xincement。 <?php $xincrement = bcdiv(200,$columns-1,0); ?> bcdiv用第二个参数除以第一个参数,并且返回根据第三个参数所指定的小数位数的值。为了使用BCMath 函数,你需要在Unix下将其编译到PHP中,但是Windows版本已经将其编译进去了。README.BCMATH在PHP源代 码的根目录中,它将解释在哪和如何做。 y值将与$max数值成比例,所以我们所能做的就是用$max来除g_num得到比例的小数值,然后乘以200 -- 图像的高度。 <?php $y = bcmul(bcdiv($salesRow[0],$max,2),200,2); ?> $salesRow[0]是当前行的g_num值,除上$max,并且结果定为小数部分为2位。然后使用bcmul将结果与200 相乘。 然后可以做的就是在整个数组中循环,使用当前元素作为线的开始,当前元素+1作为线的结束。因为最 后一个元素将永远不会是一行的开始,我们必需将循环减1,所以将当小于或等于$columns-1 时循环改为小 于$columns-1时循环。 让我们看一下迄今为止的代码: <?php // 发送头信息和创建初始的空白画布 Header( "Content-type: image/gif"); $image = imagecreate(200,200); // 分配一些颜色 $red = ImageColorAllocate($image,255,0,0); $blue = ImageColorAllocate($image,0,0,255); $white = ImageColorAllocate($image,255,255,255); $grey = ImageColorAllocate($image,200,200,200); // 创建一个初始的灰色矩形用于绘图 ImageFilledRectangle($image,0,0,200,200,$grey); // 连接mysql服务器并选择数据库 $connect = mysql_connect("","root",""); mysql_select_db("graphing",$connect); // 找到结果集中的最大数值 $sql = "SELECT MAX(g_num) FROM sales"; $maxResult = mysql_query($sql,$connect); $max = mysql_result($maxResult,0,0); // 得到伦敦的结果集 $sql = "SELECT g_num FROM sales WHERE g_team='London' ORDER BY g_month"; $salesResult = mysql_query($sql,$connect); // 找到返回多少列,就是'columns'的数值 $columns = mysql_num_rows($salesResult); // $x每次增加多少量? $xincrement = bcdiv(200,$columns-1,0); $x=0; // $i 将记录行的数值 $i=0; // 在我们所有的数据行中循环 while($salesRow=mysql_fetch_array($salesResult)) { // 象上面所讨论地计算y的坐标值 $y = bcmul(bcdiv($salesRow[0],$max,2),200,2); // 在$points数组中增加值 $points[$i][0] = $x; $points[$i][1] = $y; // 增加$x的值用$xincrement $x+=$xincrement; // 增加 $i $i++; } // 现在我们在$points数组中循环,此时$i小于$columns-1 for($i=0;$i<$columns-1;$i++) { // 我们传递 $points[$I][0] 作为第一个x坐标,$points[$I][1] 为第一个y坐标 // $points[$I+1][0], $points[$I+1][1] 将是下一个x,y坐标集 ImageLine($image,$points[$i][0],$points[$i][1],$points[$i+1][0], $points[$i+1][1],$red); } // 输出GIF给浏览器并且释放内存 ImageGIF($image); ImageDestroy($image); ?> 这样将给出我们如下的结果: <img src="http://www.phpstar.com/pic/2000090702.gif"> 它既不正确也很气人。问题在于我们是按传统的x和y坐标方法处理的,这种方法是从左下角向外发散的。 Image函数的坐标系统是从左上角发散的,所以这时我们的x位置是正确的,我们的y位置弄反了。 我们需要做的就是修改确定y位置的代码以便按相反的方式工作 -- 改变行 <?php ImageLine($image,$points[$i][0],$points[$i][1],$points[$i+1][0],$points[$i+1][1],$red); ?> 变成读取: <?php ImageLine($image,$points[$i][0],200-$points[$i][1],$points[$i+1][0],200-$points[$i+1][1],$red); ?> 我们将得到图形: <img src="http://www.phpstar.com/pic/2000090703.gif"> 现在我们需要做的是加入一条线,它是将亚特兰大的数据进行了图形化。 <?php $sql = "SELECT g_num FROM sales WHERE g_team='Atlanta' ORDER BY g_month"; $salesResult = mysql_query($sql,$connect); $columns = mysql_num_rows($salesResult); $xincrement = bcdiv(200,$columns-1,0); $x=0; $i=0; while($salesRow=mysql_fetch_array($salesResult)) { $y = bcmul(bcdiv($salesRow[0],$max,2),200,2); $points[$i][0] = $x; $points[$i][1] = $y; $x+=$xincrement; $i++; } for($i=0;$i<$columns-1;$i++) { ImageLine($image,$points[$i][0],200-$points[$i][1],$points[$i+1][0],200-$points[$i+1][1],$blue); } ?> <img src="http://www.phpstar.com/pic/2000090704.gif"> 我们用在这个例子中的数据是静态的,在以后的部分我们将看一下如何处理动态数据,并且看一下在图 表中增加一些轴线和标签。 译者注: 本文中的例子,我已经在php 3.0.16下,使用旧版的gd库测试成功。对于高版本的php(4.0以上版本)由于不再支持gif文件,所以我将Imagegif改成了ImagePNG函数执行后,成功。而且对于Header输出的MIME类型可以仍然使用image/gif格式说明。如果大家有什么建议欢迎来信。对于php 4.0.2版本与其使用的gd库均可从http://www.mm4.de/处下载。不过这个网站上则是全的文件包而不是独立的动态库。还有一点要说明的是这里我所说的版本全部是windows下的。至于linux则可以直接在编译时设定即可。 <phpfans.net收集整理 |