18c04-1.php
来自「介绍PHP5的给类型函数应用」· PHP 代码 · 共 332 行
PHP
332 行
<?php// A class for drawing charts that allows its configuration to be pushed// into it via public propertiesclass MultiGraph { // Public class members, all of these need filled in before drawing. public $border_color; // Color of the border/text public $grid_color; // Color of the grid lines public $data_color; // Color of any data blocks public $g; // Graphics object public $data; // Data to turn into a graph public $draw_border = true; // Should the border be drawn? public $horizontal_grid_segments = 5; // How many horizontal grid lines? public $vertical_grid_segments = 0; // How about vertical ones? public $x = 0; // X value of the upper left corner of CHART area public $y = 0; // Y value public $w = 200; // Width of actual chart area public $h = 100; // Height of actual chart area public $point_size = 5; // Size of data points when doing a Point Chart public $y_axis_autolabel = true; // Generate labels for Y axis? public $x_axis_autolabel = true; // Generate labels for X axis? public $font = 'arial'; // Font to use public $fontsize = 8; // Size of font. // Constructor method. Requires the graphics object public function __construct($graphics) { // Store the graphics object $this->g = $graphics; // Go ahead and turn on antialiasing imageantialias($this->g, true); } // Method to make it easy to set dimensions public function setDimensions($x, $y, $w, $h) { // Just do it $this->x = $x; $this->y = $y; $this->h = $h; $this->w = $w; } // The method that will draw a line graph to the screen! public function drawLineGraph() { // We are asked to draw a line graph. First of all draw the borders $this->_drawBorder(); // Calculate the conversion factors to scale data to space given $yscale = $this->_calcYScale(); $xscale = $this->_calcXScale(); // Draw a grid if asked $this->_drawHorizontal(); $this->_drawVertical(); // Now we are ready for the data (finally) // We are doing a line graph, assume the key is the X value & sort. // Since we are sorting, make a copy to not mess up the real data $tmpdata = $this->data; ksort($tmpdata); // Now step through it, drawing the lines as appropriate: list($ldx, $ldy) = each($tmpdata); while (list($dx, $dy) = each($tmpdata)) { // Draw the line from the last x,y pair, to the current one imageline($this->g, $this->x + $ldx * $xscale, $this->y + $this->h - $ldy * $yscale, $this->x + $dx * $xscale, $this->y + $this->h - $dy * $yscale, $this->data_color); // Reset data for next loop $ldx = $dx; $ldy = $dy; } } // The method that will draw a point plot to the screen. public function drawPointGraph() { // We are asked to draw a point graph. First draw the borders $this->_drawBorder(); // Calculate the conversion factors to scale data to space given $yscale = $this->_calcYScale(); $xscale = $this->_calcXScale(); // Draw a grid if asked $this->_drawHorizontal(); $this->_drawVertical(); // Now we are ready for the data - Now step through it foreach ($this->data as $dx => $dy) { // Draw the point for this data: imagefilledellipse($this->g, $this->x + $dx * $xscale, $this->y + $this->h - $dy * $yscale, $this->point_size, $this->point_size, $this->data_color); } } // The method that will draw a bar graph // NOTE: Bar graphs assume that the keys of the array are // labels, not 'x' values. public function drawBarGraph() { // We've been asked to draw a Bar graph. First draw the borders $this->_drawBorder(); // Calculate the conversion factors to scale data to space given $yscale = $this->_calcYScale(); // Draw a grid if asked $this->_drawHorizontal(); // Precalculate a few items to be efficient: // The width of each 'section': $section = (float) $this->w / count($this->data); // The width of a bar, we want it 70% of section: $bar = (int) ($section * 0.7); // Loop once per data item that we have - assume they are in order $count = 0; foreach ($this->data as $label => $val) { $count++; // Draw the bar to the appropriate height & width: // First as a colored filled rectangle: imagefilledrectangle($this->g, $this->x + ($section * $count) - $bar, $this->y + $this->h, $this->x + ($section * $count), $this->y + $this->h - $val * $yscale, $this->data_color); // Then as an outline: imagerectangle($this->g, $this->x + ($section * $count) - $bar, $this->y + $this->h, $this->x + ($section * $count), $this->y + $this->h - $val * $yscale, $this->border_color); // Now, since vertical grids don't really exist for bar graphs // We need to create the labels ourselves if ($this->x_axis_autolabel) { // Calculate the width of the box needed by the bounding box $box = imagettfbbox($this->fontsize, 270, $this->font, $label); $texwidth = abs($box[4] - $box[0]); // Draw it going vertical imagettftext($this->g, $this->fontsize, 270, ($this->x + ($section * $count)) - ($bar / 2) - ($texwidth / 2), $this->y + $this->h + 4, $this->border_color, $this->font, $label); } } } // Support function to draw the border: private function _drawBorder() { if ($this->draw_border) { // Vertical one imageline($this->g, $this->x, $this->y, $this->x, $this->h + $this->y, $this->border_color); // Horizontal one imageline($this->g, $this->x, $this->h+$this->y, $this->w + $this->x, $this->h + $this->y, $this->border_color); } } // Support function for calculating the Y scale private function _calcYScale() { // Add a fudge for visual purposes so it doesn't ever hit the top. return (float) $this->h / $this->_calcYMax(); } // Support function for calculating the X scale private function _calcXScale() { return (float) $this->w / $this->_calcXMax(); } // Support function for calculating the maximum Y value, for scaling/etc private function _calcYMax() { // Add a fudge for visual purposes so it doesn't ever hit the top. // Also force round it to only 2 significant digits // as this will make it look 'clean' $max = (float) max($this->data) * 1.05; // Get the 'length' of this: $len = strlen((int)$max); // Find a 2 digit ceiling, if less than 2 digits, just return it: if ($len < 2) { return $max; } else { // Keep the first two digits and pad with zeros: return intval(substr($max, 0, 2) . str_repeat('0', $len - 2)); } } // Support function for calculating the maximum X value, for scaling/etc private function _calcXMax() { return max(array_keys($this->data)); } // Support function for drawing the Horizontal Grid private function _drawHorizontal() { if ($this->horizontal_grid_segments) { // Figure out their placement foreach(range(1, $this->horizontal_grid_segments) as $hg) { // Y height for this is: $yheight = (int) $this->y + $this->h - ($hg * ($this->h / $this->horizontal_grid_segments)); imageline($this->g, $this->x + 1, $yheight, $this->w + $this->x, $yheight, $this->grid_color); // Now, IF they wanted automatic labels, give 'em if ($this->y_axis_autolabel) { // Calculate the value for here, and display it $ax_step = (int)(($this->_calcYMax() / $this->horizontal_grid_segments) * $hg); // Calculate the width of the box needed to display // this: Use the lower left X (0) and the upper right // X (4) to calculate width: $box = imagettfbbox($this->fontsize, 0, $this->font, $ax_step); $texwidth = abs($box[4] - $box[0]); $texheight = abs($box[5] - $box[1]); // Draw it right justified: imagettftext($this->g, $this->fontsize, 0, $this->x - 3 - $texwidth, $yheight + $texheight / 2, $this->border_color, $this->font, $ax_step); } } } } // Support function for drawing the Vertical Grid private function _drawVertical() { if ($this->vertical_grid_segments) { // Figure out their placement foreach(range(1, $this->vertical_grid_segments) as $vg) { // X location for this is: $xloc = (int) ($this->x + ($vg * ($this->w / $this->vertical_grid_segments))); imageline($this->g, $xloc, $this->y, $xloc, $this->y + $this->h - 1, $this->grid_color); // Now, IF they wanted automatic labels, give 'em if ($this->x_axis_autolabel) { // Calculate the value for here, and display it $ax_step = (int)(($this->_calcXMax() / $this->vertical_grid_segments) * $vg); // Calculate the width of the box needed to display // this: Use the lower left X (0) and the upper // right X (4) to calculate width: $box = imagettfbbox($this->fontsize, 270, $this->font, $ax_step); $texwidth = abs($box[4] - $box[0]); // Draw it going vertical imagettftext($this->g, $this->fontsize, 270, $xloc - $texwidth / 2, $this->y + $this->h + 3, $this->border_color, $this->font, $ax_step); } } } } }// Pre/setup for the date functions:date_default_timezone_set('America/New_York');// Create a blank image to test with.$gfx = imagecreatetruecolor(950, 650);// Declare a few colors$red = imagecolorallocate($gfx, 255, 0, 0);$manilla = imagecolorallocate($gfx, 255, 255, 245);$black = imagecolorallocate($gfx, 0, 0, 0);$lgray = imagecolorallocate($gfx, 200, 200, 200);// Color our backgroundimagefill($gfx, 0, 0, $manilla);// Initialize a new Multigraph$graph = new MultiGraph($gfx);$graph->border_color = $black;$graph->grid_color = $lgray;$graph->data_color = $red;$graph->vertical_grid_segments = 10;// Create some fake data// Generate up to 50 random points of data, with random values:$chartdata = array();for ($i = 0; $i < 50; $i++) { $chartdata[rand(1,200)] = rand(1,1000);}$graph->data = $chartdata;// Ok, output a line graph$graph->setDimensions(50, 50, 300, 200);$graph->drawLineGraph();// Now do it as a point graph with some changed grid parameters$graph->horizontal_grid_segments = 9;$graph->vertical_grid_segments = 15;$graph->setDimensions(50, 350, 300, 200);$graph->drawPointGraph();// Finally lets create a bar graph, we need new data for that, with labels.// Automatically generate some that is based on Month names.$bardata = array();foreach(range(1,12) as $mon) { $bardata[date('F', mktime(0, 0, 0, $mon))] = rand(1,5000);}// Change some options, and display the BIG bar graph:$cyan = imagecolorallocate($gfx, 0, 255, 255);$graph->data_color = $cyan;$graph->fontsize = 11;$graph->horizontal_grid_segments = 12;$graph->setDimensions(450, 40, 400, 500);$graph->data = $bardata;$graph->drawBarGraph();// Output our sample as a PNGheader('Content-type: image/png');imagepng($gfx);?>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?