序 PHP在图像操作方面的表现非常出色,我们只需借助可以免费得到的GD库便可以轻松实现图、表勾画。下面将分别介绍笔者实现
的饼状图、折线图和柱状图以及他们的使用方法,这几段代码的特点就是不需要再把它们复制到你的代码之中,只需要把计算得到的数据作为参数传入,即可得到相
应的图形效果 开发环境:PHP Version 4.3.6+GD Version bundled (2.0.22
compatible) 由于作者水平有限,文章中难免存在错误,我将非常感激您的指正 代码中所有使用的函数的说明,请参见
php开发文档 点这里获得最
新版 饼状图
设计思路饼状图表对于查看一个值占总值的百分比是一个好的方法。我们就用PHP来
实现一个饼形图表。 它的设计思想是: 1 接受参数,得到所有数值的和,得到每一个值占数值总和的比例。 2
根据比例计算每一个色块在图中的圆周角度 3 要产生立体效果,只需要用深颜色画出阴影就可以了
实现过程<? //参数以a为参数名传入,a的文本形态
应该是用“,”分割的若干数字连接的字符串 //这里首先判断a是否存在 if($_GET["a"]=="") die("0"); //
将得到的数据分解,存入数组$shuju中 $shuju=split(",",$_GET["a"]); //再次判断数据的合法性,返回
错误代码 if(count($shuju)==0) die("2"); //定义整个图形的宽度和高度 //读者可以根据需要修
改这两个变量的值 $tukuan=300; $tugao=150; //定义一个数组,用来存放每一个色块的角度范围 $jiaodu
= array(); //定义存贮数据和的变量 $total=0; //遍历数组求和 for ($i = 0; $i
< count($shuju); $i++) { if(!is_numeric($shuju[$i])) die("1");
$total+=$shuju[$i]; } //再次遍历,计算色块角度并存入数组 for ($i = 0; $i <
count($shuju); $i++) { array_push ($jiaodu,
round(360*$shuju[$i]/$total)); } //创建图像 $image =
imagecreate($tukuan, $tugao); //定义一个灰色背景色,这个颜色其实就是大家很熟悉的页面色系16进制数字表示
的#EEEEEE $white = imagecolorallocate($image, 0xEE, 0xEE, 0xEE); //
再定义10对深浅对应的彩色,存入二维数组 $yanse = array( array(
imagecolorallocate($image, 0x97, 0xbd, 0x00),
imagecolorallocate($image, 0x00, 0x99, 0x00),
imagecolorallocate($image, 0xcc, 0x33, 0x00),
imagecolorallocate($image, 0xff, 0xcc, 0x00),
imagecolorallocate($image, 0x33, 0x66, 0xcc),
imagecolorallocate($image, 0x33, 0xcc, 0x33),
imagecolorallocate($image, 0xff, 0x99, 0x33),
imagecolorallocate($image, 0xcc, 0xcc, 0x99),
imagecolorallocate($image, 0x99, 0xcc, 0x66),
imagecolorallocate($image, 0x66, 0xff, 0x99) ), array(
imagecolorallocate($image, 0x4f, 0x66, 0x00),
imagecolorallocate($image, 0x00, 0x33, 0x00),
imagecolorallocate($image, 0x48, 0x10, 0x00),
imagecolorallocate($image, 0x7d, 0x64, 0x00),
imagecolorallocate($image, 0x17, 0x30, 0x64),
imagecolorallocate($image, 0x1a, 0x6a, 0x1a),
imagecolorallocate($image, 0x97, 0x4b, 0x00),
imagecolorallocate($image, 0x78, 0x79, 0x3c),
imagecolorallocate($image, 0x55, 0x7e, 0x27),
imagecolorallocate($image, 0x00, 0x93, 0x37) ) ); //由下至上画
10个像素高的深色饼图,作为阴影 $yuanxin_x=$tukuan/2; for ($h = $tugao/2+5; $h
> $tugao/2-5; $h--) { $kaishi=0; $jieshu=0; for ($i =
0; $i < count($shuju); $i++) { $kaishi=$kaishi+0;
$jieshu=$kaishi+$jiaodu[$i]; $yanse_i=fmod($i,10);
imagefilledarc($image,$yuanxin_x,$h,$tukuan,$tugao-20,$kaishi,$jieshu,$yanse[1][$yanse_i],IMG_ARC_PIE);
$kaishi+=$jiaodu[$i]; $jieshu+=$jiaodu[$i]; } } //
在最高处(也就是$h最小时)画一个浅色饼图,这个浅色图跟先画上的深色饼图就能产生立体效果了 for ($i = 0; $i <
count($shuju); $i++) { $kaishi=$kaishi+0;
$jieshu=$kaishi+$jiaodu[$i]; $yanse_i=fmod($i,10);
imagefilledarc($image, $yuanxin_x, $h, $tukuan, $tugao-20, $kaishi,
$jieshu, $yanse[0][$yanse_i], IMG_ARC_PIE); $kaishi+=$jiaodu[$i];
$jieshu+=$jiaodu[$i]; } //设定文件头 header('Content-type:
image/png'); //输出图像 imagepng($image); //释放资源 imagedestroy($image); ?> 使用方法在需要显示图像的位置插入如下代码 <img
src="bing_img.php?a=3,2,3,4"/> a的文本格式是由“,”连接的若干个数据的字符串,get方式传入。 颜
色图例如下,请自行排列: 实现效果
折线图
设计思路用折线图表查看某一数据在单位时段内的变化趋势是一个好的选择。我们就用PHP来实现一个动态折线图表。 它的设计思想是: 1
接受参数,得到所有数值的和,得到数据的最大值以确定纵轴的最大刻度值 2 根据数据个数确定图像的宽度,并画出横轴和纵轴坐标及刻度 3
画直线连接各点,为每个点填充一个2*2的矩形,突出点的位置 4 在每个点的右上方标注每个点的数据值 实现过程<? $img_gao=170; $img_kuan=0; $jiange=30;
//横坐标点与点之间的间隔,生成的图片宽度会根据传入数据的多少而自动变化 $zuo=20;//左侧留空 $you=20;//右侧留空 $shang=20;
//上留空 $xia=20;//下留空 $zuidashujuzhi=1; $p_x = array();//点横坐标 $p_y
= array();//点纵坐标 $y_name=split(",",$_GET["x_name"]); if
($_GET["a"]=="") die("error id:0"); $shuju=split(",",$_GET["a"]); //
得到纵轴最大值 for($i=0;$i<count($shuju);$i++){
if(!is_numeric($shuju[$i])) die("error id:1");
if($shuju[$i]>$zuidashujuzhi) $zuidashujuzhi=$shuju[$i]; } //得到
图像宽度 $img_kuan=$zuo+$you+count($shuju)*$jiange; //然后创建图像资源 $image
= imagecreate($img_kuan,$img_gao); //灰色背景 $white =
imagecolorallocate($image, 0xEE, 0xEE, 0xEE); //坐标轴用黑色显示 $zuobiao_yanse
= imagecolorallocate($image, 0x00, 0x00, 0x00); //折线用蓝色显示 $xian_yanse
= imagecolorallocate($image, 0x00, 0x00, 0xFF); //画坐标 //横轴 imageline
( $image, $zuo, $img_gao-$xia, $img_kuan-$you/2, $img_gao-$xia,
$zuobiao_yanse); //纵轴 imageline ( $image, $zuo, $shang/2, $zuo,
$img_gao-$xia, $zuobiao_yanse); //得到每个点的坐标 for($i=0;$i<count($shuju);$i++){
array_push ($p_x, $zuo+$i*$jiange); array_push ($p_y,
$shang+round(($img_gao-$shang-$xia)*(1-$shuju[$i]/$zuidashujuzhi))); } //
纵轴刻度 imageline ( $image, $zuo, $shang, $zuo+6, $shang,
$zuobiao_yanse); imagestring ( $image, 1, $zuo/4,
$shang,$zuidashujuzhi, $zuobiao_yanse); imageline ( $image, $zuo,
$shang+($img_gao-$shang-$xia)*1/4, $zuo+6,
$shang+($img_gao-$shang-$xia)*1/4, $zuobiao_yanse); imagestring (
$image, 1, $zuo/4, $shang+($img_gao-$shang-$xia)*1/4,$zuidashujuzhi*3/4,
$zuobiao_yanse); imageline ( $image, $zuo,
$shang+($img_gao-$shang-$xia)*2/4, $zuo+6,
$shang+($img_gao-$shang-$xia)*2/4, $zuobiao_yanse); imagestring (
$image, 1, $zuo/4, $shang+($img_gao-$shang-$xia)*2/4,$zuidashujuzhi*2/4,
$zuobiao_yanse); imageline ( $image, $zuo,
$shang+($img_gao-$shang-$xia)*3/4, $zuo+6,
$shang+($img_gao-$shang-$xia)*3/4, $zuobiao_yanse); imagestring (
$image, 1, $zuo/4, $shang+($img_gao-$shang-$xia)*3/4,$zuidashujuzhi*1/4,
$zuobiao_yanse); //横轴刻度 for($i=0;$i<count($shuju);$i++){
imageline ( $image, $zuo+$i*$jiange, $img_gao-$xia, $zuo+$i*$jiange,
$img_gao-$xia-6, $zuobiao_yanse); imagestring ( $image, 1,
$zuo+$i*$jiange-$jiange/4, $shang+($img_gao-$shang-$xia)+2,$y_name[$i],
$zuobiao_yanse); } //折线 $shuju_yanse_int=0; for($i=0;$i<count($shuju);$i++){
if($i+1<>count($shuju)){ imageline ( $image, $p_x[$i],
$p_y[$i], $p_x[$i+1], $p_y[$i+1], $xian_yanse);
imagefilledrectangle($image, $p_x[$i]-1, $p_y[$i]-1, $p_x[$i]+1,
$p_y[$i]+1, $xian_yanse); } } //上一个循环没有画出最后一个点效果,这里还要追加 imagefilledrectangle($image,
$p_x[count($shuju)-1]-1, $p_y[count($shuju)-1]-1,
$p_x[count($shuju)-1]+1, $p_y[count($shuju)-1]+1, $xian_yanse);
//
标注数据值 for($i=0;$i<count($shuju);$i++){ imagestring ( $image,
3, $p_x[$i]+4, $p_y[$i]-12,$shuju[$i], $zuobiao_yanse); } //设定文件头 header('Content-type:
image/png'); //输出图像 imagepng($image); //释放资源 imagedestroy($image); ?>
使用方法在需要显示图像的位置插入如下代码 <img
src="zhexian_img.php?a=5.4,2,30.2,4,0,6,7.7,3.8,2,3,4"/> 其中a的值由你自己
计算得出 a的文本格式是由“,”连接的若干个数据的字符串,get方式传入。 由于往图形里写入中文需要更多PHP环境配置,所以这
里给出一个html解决方案,实用也很灵活: 大家只需要根据数据个数的不同,动态生成一个表格放置横轴坐标刻度名称就行了,像这样 <table
width="550" border="0" cellspacing="0" cellpadding="0"> <tr
align="center"> <? for($i=0;$i<12;$i++) { echo
"<td width=\"30\">".$i."月 | ";
}
?>