PHP 画出线形图表(函数)

发布时间:2009年02月03日      浏览次数:1615 次
<?php
//注:本程序测试通过,如果复制无法运行,请先将以下所使用的背景图片及字体文件拷贝到tmp文件夹内,如果找不到文件将运行出错
//背景图片为bg.jpg;字体文件为字体文件为font_zh.ttf(中文字体)、font_en.ttf(英文字体)。
////////////////////////////////////////////////////////////////////////////////////////////
//调用函数
////////////////////////////////////////////////////////////////////////////////////////////
/*
//线形数组,数据源
$data_source_arr[] = array(42, 300, 14, 123, 100, 77, 9, 177, 50, 80, 200, 150);
$data_source_arr[] = array(142, 180, 104, 23, 80, 177, 109, 67, 190, 34, 99, 140);
$data_source_arr[] = array(20, 80, 150, 210, 90, 60, 200, 180, 100, 50, 70, 40);
//$data_source_arr[] = array(90, 180, 50, 20, 190, 160, 50, 80, 10, 150, 170, 240);
//$data_source_arr[] = array(190, 10, 20, 40, 60, 130, 160, 240, 110, 250, 270, 300);
$x_arr      = array(" 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", "10", "11", "12");//x坐标值(可省略,省略后不显示)
$y_arr      = array(" $0", " $50", "$100", "$150", "$200", "$250", "$300");//y坐标值(可省略,省略后自动计算)
$note_arr = array("2006", "2007", "2008"); //文本注释(可省略,省略后不显示)
create_xianxing_img($data_source_arr, $x_arr, $y_arr, $note_arr, 500, 300, "", "标题");//显示图片
//create_xianxing_img($data_source_arr, $x_arr, $y_arr, $note_arr, 500, 300, "1.jpg", "标题");//生成图片1.jpg
*/
////////////////////////////////////////////////////////////////////////////////////////////
// 画出图表( 主函数create_xianxing_img() )
// 参数说明:$data_source_arr数据源(可以是多维或一维数组), $x_arr(一维数组)X坐标显示的文本, $y_arr(一维数组)Y坐标显示的文本,$width图形区域的宽度,$height图形区域的高度,$create_img_file要生成的图片路径,$title图表的标题
////////////////////////////////////////////////////////////////////////////////////////////
function create_xianxing_img($data_source_arr, $x_arr="", $y_arr="",$note_arr="",$width=0,$height=0,$create_img_file="",$title=""){
      $class_tmp_url = "../class/images/"; //指定图片与字体的存放路径
      $data_num = count($data_source_arr);//条形的数量
      if ( $data_num <= 0 ){
            return false;
            break;
      }
      $tx_width = 500; //图形的宽
      $tx_height = 300; //图形的高
      if ( $width > 0 ) $tx_width = $width;
      if ( $height > 0 ) $tx_height = $height;
      
      $maxvalue = array_max($data_source_arr);//找出数组中最大的数值
      if ( !is_array($y_arr) ){
            $y_arr = get_y_arr($maxvalue);
      }
      $y_arr_max = array_max($y_arr);
      if ( $maxvalue < $y_arr_max ) $maxvalue = $y_arr_max;
      
      //定义边界距离 
      $top      = 30;
      $left      = 20;
            $left_y_txt_len = array_max_len($y_arr)*8;
            if ( $left_y_txt_len > $left ) $left = $left_y_txt_len; //左边距
            if ( $left_y_txt_len > 65 ) $left = 65; //如果字符串长度大于150,则设置左边最大距离为50
      $right      = 20;
            $right_note_txt_len = array_max_len($note_arr)*8+30;
            if ( $right_note_txt_len > $left ) $right = $right_note_txt_len; //右边距
            if ( $right_note_txt_len > 65 ) $right = 65; //如果字符串长度大于150,则设置左边最大距离为50
      $bottom = 20;
      $img_width = $tx_width + $left + $right; //整张图片的宽
      $img_height = $tx_height + $top + $bottom; //整张图片的高
      $bg= $class_tmp_url."bg.jpg";      //背景图片路径
      $im = imagecreatefromjpeg($bg);
      $img = imagecreatetruecolor($img_width,$img_height) ;
      
      //背景图
      @imagecopyresized($img,$im,0,0,0,0,$img_width,$img_height,imagesx($im),imagesy($im));
      
      //定义颜色
      imagedestroy($im);
      $white            = imagecolorallocate($img, 255,255,255);
      $black            = imagecolorallocate($img, 0,0,0);
      $red            = imagecolorallocate($img, 255,0,0);
      $green            =       imagecolorallocate($img, 0,255,0);
      $blue            = imagecolorallocate($img, 0,0,255);
      //定义线条颜色数组
      $color_arr[0] = imagecolorallocate($img, 0,0,0);
      $color_arr[1] = imagecolorallocate($img, 255,0,0);
      $color_arr[2] = imagecolorallocate($img, 0,255,0);
      $color_arr[3] = imagecolorallocate($img, 0,0,255);
      $color_arr[4] = imagecolorallocate($img, 255,0,255);
      $color_arr[5] = imagecolorallocate($img, 255,255,0);
      $color_arr[6] = imagecolorallocate($img, 100,90,80);
      $color_arr[7] = imagecolorallocate($img, 20,80,0);
      $color_arr[8] = imagecolorallocate($img, 150,255,0);
      $color_arr[9] = imagecolorallocate($img, 0,240,250);
      
      //定义字体
      $use_font_file = false; //定义是否使用字体,true或false
      $font_zh = $class_tmp_url.'font_zh.ttf'; //中文,使用中文字体才能显示中文
      $font_en = $class_tmp_url.'font_en.ttf'; //英文
      if ( $use_font_file ){
            $font_type = 0; //定义使用英文字体还是中文字体,0表示英文,1表示中文(默认为0英文)
            if ( $font_type == 1 ){ //指定字体文件路径
                  $fontfile = $font_zh; //中文
            }else{
                  $fontfile = $font_en; //英文
            }
      }
      
      //定义标题
      if( $title <> "" ){
            $title_len = strlen(trim($title));
            $left_space = ( $img_width - $title_len * 5 )/2; //文字左边距
            if ( $left_space < 0 ) $left_space = 0;
            @ImageTTFText($img,10,0,$left_space,20,$black,$font_zh,$title);
      }
      
      //画出坐标x轴 //imageline(int im, int x1, int y1, int x2, int y2, int col);
      @imageline($img,$left,$tx_height+$top,$tx_width+$left,$tx_height+$top, $white);
            //显示x轴的文本
            if ( is_array($x_arr) and count($x_arr)>0 ) $img = x_txt($img,$x_arr,$tx_width,$img_height-5 ,$tx_width,$tx_height,$top,$left,$white,$black,$use_font_file,$fontfile);
      //画出坐标y轴
      @imageline($img,$left,$top,$left,$tx_height+$top, $white);
            //显示y轴的文本
            if ( is_array($y_arr) and count($y_arr)>0 ) $img = y_txt($img,$y_arr,5,$tx_height ,$tx_width,$top,$left,$white,$black,$use_font_file,$fontfile);
      
      //--------------------------------------------------------------------------
      //线形数据,循环数组
      //--------------------------------------------------------------------------
      $arr_i = 1;//初始化线形计数
      for ( $i=0; $i<$data_num; $i++ ){
            if ( is_array($data_source_arr[$i]) ){
                  $va = $data_source_arr[$i];
                  $img = img_xianxing($img,$va,$color_arr[($arr_i%10)] ,$tx_width,$tx_height,$top,$left,$maxvalue);
                  img_note($img,$im,$note_arr,$color_arr[($arr_i%10)],$arr_i ,$tx_width,$top,$left,$white,$black,$use_font_file,$fontfile);//显示注释
                  $arr_i += 1;
            }
      }
      //--------------------------------------------------------------------------
      //生成图片
      header("Content-type: image/jpeg;");
      //$create_img_file = ""; //生成图片的路径及文件名(如:1.jpg),如果省略则直接输出显示
      $create_img_quality = 100; //生成图片的质量
      imagejpeg( $img, $create_img_file, $create_img_quality );
      imagedestroy($img);
}
//==============================================================================
// 相关函数
//==============================================================================
//显示画线形图
//参数说明:$img_为返回的图形数据,$values图形的数据值,$color线条的颜色 ,之后的参数为主函数体的变量传递
function img_xianxing($img_,$values,$color ,$tx_width,$tx_height,$top,$left,$maxvalue){
      $n=count($values);
      $step = (int)($tx_width / (($n-1>0)? $n:1) );
      for($i=0;$i<$n-1;$i++){
            if ( is_numeric($values[$i]) ){
                  $s=$values[$i];
                  $e=$values[$i+1];
                  $x_txt = $left + 10 + $step * $i;
                  $y_txt = $tx_height+$top-(round(($s / $maxvalue)*$tx_height));
                  $x_txt2 = $left + 10 + $step * ($i+1);
                  $y_txt2 = $tx_height+$top-(round(($e / $maxvalue)*$tx_height));
                  imageline($img_, $x_txt , $y_txt, $x_txt2, $y_txt2, $color);
                  /*
                  //显示数值
                  $txt = $values[$i];
                  $y_txt = $y_txt-15;
                  imagestring($img_, 2, $x_txt, $y_txt, $txt, $black );
                  if ( $i == $n-2 )imagestring($img_, 2, $x_txt2, $y_txt2, $e, $black );
                  */
            }
      }
      return $img_;
      imagedestroy($img_);
}
//显示x坐标数据
function x_txt($img_,$values,$x,$y ,$tx_width,$tx_height,$top,$left,$white,$black,$use_font_file,$fontfile){
      $n = count($values);
      $step = (int)($x / (($n-1>0)? $n:1) );
      for($i=0; $i<$n; $i++){
            $txt = $values[$i];
            $x_txt = $left + 10 + $step * $i;
            $y_txt = $y;
            if ( ! $use_font_file ){
                  imagestring($img_, 2, $x_txt, $y_txt-10, trim($txt), $black );//显示文本
            }else{
                  //ImageTTFText(数据源,字体大小,字型的角度,x坐标,y坐标,颜色,字体文件URL,输出文本)
                  @ImageTTFText($img_,9,0,$x_txt-5,$y_txt,$black,$fontfile,$txt);//显示文本,使用了字体文件,如果要显示中文,则需要此行,并使用中文字体文件
            }
            @imageline($img_,$left + 10 + $step * $i,$tx_height+$top,$left + 10 + $step * $i,$tx_height+$top+5, $white); //分段显示x坐标
      }
      @imageline($img_,$tx_width+$left,$top,$tx_width+$left,$tx_height+$top, $white); //显示最右边x坐标竖线
      return $img_;
      imagedestroy($img_);
}
//显示y坐标数据
function y_txt($img_,$values,$x,$y ,$tx_width,$top,$left,$white,$black,$use_font_file,$fontfile){
      $n = count($values);
      $num = (($n-1)>0)? ($n-1):1;
      $step = round($y / $num);
      for($i=0;$i<$n;$i++){
            $txt = $values[$i];
            $x_txt = $x;
            if ($i==0){
                  $y_txt = $y + $top;
            }else if ( $i==$n-1){
                  $y_txt = $top;
            }else{
                  $y_txt = $y + $top - $step * $i;
            }
            if ( ! $use_font_file ){
                  imagestring($img_, 2, $x_txt, $y_txt-10, trim($txt), $black );//显示文本
            }else{
                  @ImageTTFText($img_,9,0,$x_txt,$y_txt,$black,$fontfile,$txt);//显示文本,使用了字体文件,如果要显示中文,则需要此行,并使用中文字体文件
            }
            if ( $i>0 and $i<$n )@imageline($img_,$left,$y_txt,$tx_width+$left,$y_txt, $white);//分段显示y坐标
      }
      return $img_;
      imagedestroy($img_);
}
//生成图形注释
function img_note($img_,$im_,$values,$color,$item_num=1 ,$tx_width,$top,$left,$white,$black,$use_font_file,$fontfile){
      if ( !is_array($values) )return;
      $xian_width = 10;//小线的长度
      $txt = $values[$item_num-1];
      $x_txt = $tx_width+$left+5;
      $x_txt2 = $tx_width+$left+5+$xian_width;
      $y_txt = $top + 5 +(($xian_width+5)*($item_num-1));
      $y_txt2 = $y_txt;
      imageline($img_, $x_txt , $y_txt, $x_txt2, $y_txt2, $color);//显示颜色小线
      if ( ! $use_font_file ){      
            imagestring($img_, 2, $tx_width+$left+$xian_width+10, $top-2+(($xian_width+5)*($item_num-1)), $txt, $black );//显示注释文本
      }else{
            @ImageTTFText($img_,9,0, $tx_width+$left+$xian_width+10,$top+(($xian_width+5)*($item_num-1))+10,$black,$fontfile,$txt);//显示注释文本,使用了字体文件,如果要显示中文,则需要此行,并使用中文字体文件
      }
}
//找出数组中最大的数值
function array_max($arr){
      $max = 0;
      if ( is_array($arr) ){
            for ( $i=0; $i<count($arr); $i++ ){
                  if ( is_array($arr[$i]) ){
                        $str_max = array_max($arr[$i]);
                  }else{
                        $str_max = ereg_replace("([^0-9\.])", "", trim($arr[$i]));//提出数值
                  }
                  if ( is_numeric($str_max) and $str_max > $max ) $max = $str_max;
            }
      }
      return $max;
}
//找出数组中最小的数值
function array_min($arr){
      $min = 0;
      if ( is_array($arr) ){
            for ( $i=0; $i<count($arr); $i++ ){
                  if ( is_array($arr[$i]) ){
                        $str_min = array_min($arr[$i]);
                  }else{
                        $str_min = ereg_replace("([^0-9\.])", "", trim($arr[$i]));//提出数值
                  }
                  if ( is_numeric($str_min) and $str_min < $min ) $min = $str_min;
            }
      }
      return $min;
}
//找出数组中字符串最大的长度
function array_max_len($arr){
      $max_len = 0;
      if ( is_array($arr) ){
            for ( $i=0; $i<count($arr); $i++ ){
                  $str_max_len = strlen(trim($arr[$i]));
                  if ( $str_max_len > $max_len ) $max_len = $str_max_len;
            }
      }
      return $max_len;
}
//根据数据自动计算y坐标的值
function get_y_arr( &$max_value ){
      $step = 6;
      $max_value_len = strlen(ceil($max_value/10)*10);
      if ( $max_value_len > 2 ){
            $max_value = ceil($max_value / pow(10,($max_value_len - 2))) * pow(10,($max_value_len - 2));
      }
      $step_value = $max_value / $step;
      if ( ( $step_value > (int)$step_value and $step_value > 1 ) or ( $max_value % $step <> 0 and $step_value < 1 ) ){
            $step = 5;
            $step_value = $max_value / $step;
      }
      if ( $step_value > 1 )$step_value = ceil($step_value);
      for ($i=0;$i<$step+1;$i++){
            $arr[] = $step_value * $i;
      }
      return $arr;
}
?>
文章来源:桂林唯创网络
免责声明:本站相关技术文章信息部分来自网络,目的主要是传播更多信息,如果您认为本站的某些信息侵犯了您的版权,请与我们联系,我们会即时妥善的处理,谢谢合作!