Viewing file: phpgraphlib_pie.php (13.54 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php /////////////////////////////////////////////////////////// //PHPGraphLib - PHP Graphing Library v2.31 - Pie Chart Extension //Author: Elliott Brueggeman //PHP v4.04 + compatible //Please visit www.ebrueggeman.com for usage policy //and documentation + examples /////////////////////////////////////////////////////////// class PHPGraphLibPie extends PHPGraphLib { //user changeable defaults var $pie_precision = 0; //number of significant digits in label % var $bool_legend = true; var $bool_data_labels = true; var $pie_3D_height_percent = 4; //is % of total width var $pie_legend_text_width = 6; //in px... var $pie_legend_text_height = 12; var $pie_label_text_width = 6; var $pie_label_text_height = 12; var $pie_legend_padding = 5; //padding inside legend box //default colors, in order of display on graph - you can change order if needed var $pie_avail_colors = array('pastel_orange_1','pastel_orange_2','pastel_blue_1','pastel_green_1','clay', 'pastel_blue_2','pastel_yellow','silver','pastel_green_2','brown','gray','pastel_purple', 'olive', 'aqua','yellow','teal','lime'); //internal defaults - change not recommended var $pie_center_y_offset = 50; //in % var $pie_center_x_offset = 50; //in % var $pie_center_legend_scale = 55; //offset in % of existing coords when legend var $pie_width_percent = 75; //default width % of total width var $pie_height_percent = 28; var $pie_label_scale = 90; //in % scale width/height if data labels var $pie_legend_scale = 64;//in % scale width/height if legend //internals - do not change var $pie_width; var $pie_height; var $pie_center_x; var $pie_center_y; var $pie_legend_width; var $pie_legend_height; var $pie_legend_x; var $pie_legend_y; var $pie_data_max_length = 0; var $pie_color_pointer = 0; var $pie_data_array_percents; var $pie_data_label_space; var $pie_3D_height; function PHPGraphLibPie($width = '', $height = '') { PHPGraphLib::PHPGraphLib($width, $height); } function initialize() { PHPGraphLib::initialize(); $this->pie_data_array_percents = array(); } function calcCoords() { //CALC COORDS OF PIE CENTER AND WIDTH/HEIGHT $this->pie_width = $this->width * ($this->pie_width_percent / 100); $this->pie_height = $this->width * ($this->pie_height_percent / 100); $this->pie_center_y = $this->height * ($this->pie_center_y_offset / 100); $this->pie_center_x = $this->width * ($this->pie_center_x_offset / 100); //SET DATA LABEL SPACING if ($this->bool_data_labels) { //SET TO NUMBER OF PIXELS THAT ARE EQUAL TO TEXT WIDTH //7 IS A BASE SPACER THAT ALL LABELS GET $this->pie_data_label_space = 7 + $this->width / 30; $this->pie_width *= $this->pie_label_scale / 100; $this->pie_height *= $this->pie_label_scale / 100; } if ($this->bool_legend) { //COMPENSATE FOR LEGEND WITH LESSER PRESET PERCENT $this->pie_width *= $this->pie_legend_scale / 100; $this->pie_height *= $this->pie_legend_scale / 100; $this->pie_center_x *= $this->pie_center_legend_scale / 100; } $this->pie_3D_height = $this->pie_3D_height_percent * ($this->pie_width / 100); } function setupData() { //IN THE PIE EXTENSION, THIS WILL CALCULATE THE TOTAL SUM AND THE CORRESPONDING PERCENTAGES if ($this->data_set_count==1) { $sum = array_sum($this->data_array[0]); if ($sum > 0) { foreach ($this->data_array[0] as $dataText => $dataValue) { $this->pie_data_array_percents[] = $dataValue / $sum; //FIND DATA TEXT LENGTH $len = strlen($dataText); if ($len > $this->pie_data_max_length){ $this->pie_data_max_length = $len; } } $this->bool_bars_generate = true; } else { $this->bool_bars_generate = false; $this->error[] = "Sum of data must be greater than 0."; } } else { $this->error[]="Multiple datasets not allowed with pie charts"; } } function generateGrid() {} function generateLegend() { $maxChars = NULL; //CALC HEIGHT / WIDTH BASED ON # OF VALUES $this->pie_legend_height = ($this->pie_legend_text_height * $this->data_count) + (2 * $this->pie_legend_padding); $this->pie_legend_width = ($this->pie_data_max_length * $this->pie_legend_text_width) + (6 * $this->pie_legend_padding); //ALLOTTED SPACE DOES NOT INCLUDE PADDING AROUND LEGEND (SMALLER) $allottedSpace = $this->width - $this->pie_center_x - ($this->pie_width / 2) - (2 * $this->pie_legend_padding); if ($this->bool_data_labels) { //ALSO COMPENSATE FOR DISPLAYED TEXT DATA % ON GRAPH $allottedSpace -= ((4 + $this->pie_precision) * $this->pie_label_text_width) + $this->pie_data_label_space; } //CHECK TO MAKE SURE WE ARE NOT > ALLOTTED SPACE if ($this->pie_legend_width > $allottedSpace) { //IF WE ARE, ADJUST WIDTH AND MAX LENGTH FOR DATA VALUES //4 = Padding | Swatch(Padding Width) | Padding | ...text... |Padding $swatchAndPaddingWidth = 4 * $this->pie_legend_padding; //MAX CHARS = ALOTTED SPACE - ENOUGH ROOM FOR SWATCHES / TEXT WIDTH $maxChars = floor(($allottedSpace - $swatchAndPaddingWidth) / $this->pie_legend_text_width); $this->pie_legend_width = ($maxChars * $this->pie_legend_text_width) + $swatchAndPaddingWidth; } else { //WE DIDNT GO OVER ALLOTTED SPACE, SO WE SHOULD ADJUST THE CENTER OF THE PIE CHART NOW $equalSpacing = ($this->width - ($this->pie_width + $this->pie_legend_width)) / 3; //SO NOW REPOSITION CENTER AT SPACING + 1/2 PIE WIDTH $this->pie_center_x = ($this->pie_width / 2) + $equalSpacing; } //AUTO ADJUSTING FORMULA FOR POSITION OF pie_legend_x BASED ON PIE CHART SIZE $a = ($this->pie_center_x + $this->pie_width / 2); $b = $this->width - $a; $c = ($b - $this->pie_legend_width) / 2; //SET PIE X & Y ARGS $this->pie_legend_x = $a + $c; $this->pie_legend_y = ($this->height - $this->pie_legend_height) / 2; //BACKGROUND imagefilledrectangle($this->image, $this->pie_legend_x, $this->pie_legend_y, $this->pie_legend_x + $this->pie_legend_width, $this->pie_legend_y + $this->pie_legend_height, $this->legend_color); //BORDER imagerectangle($this->image, $this->pie_legend_x, $this->pie_legend_y, $this->pie_legend_x + $this->pie_legend_width, $this->pie_legend_y + $this->pie_legend_height, $this->legend_outline_color); $xValue = $this->pie_legend_x + ($this->pie_legend_padding); $count = 0; $this->resetColorPointer(); $swatchToTextOffset = ($this->pie_legend_text_height - 6) / 2; $swatchSize = $this->pie_legend_text_height - (2 * $swatchToTextOffset); foreach ($this->data_array[0] as $dataText => $dataValue) { $yValue = $this->pie_legend_y + $this->pie_legend_text_height * $count + $this->pie_legend_padding; //DRAW COLOR BOXES $color = $this->generateNextColor(); imagefilledrectangle($this->image, $xValue, $yValue + $swatchToTextOffset, $xValue + $swatchSize, $yValue + $swatchToTextOffset + $swatchSize, $color); imagerectangle($this->image, $xValue, $yValue + $swatchToTextOffset, $xValue + $swatchSize, $yValue + $swatchToTextOffset + $swatchSize, $this->legend_swatch_outline_color); //IF LONGER THAN OUR MAX, TRIM TEXT if($maxChars){ $dataText = substr($dataText,0, $maxChars); } imagestring($this->image, 2, $xValue + (2 * $this->pie_legend_padding), $yValue, $dataText, $this->legend_text_color); $count++; } } function generateBars() { $this->resetColorPointer(); //LOOP THROUGH AND CREATE SHADAING for($i = $this->pie_center_y + $this->pie_3D_height; $i > $this->pie_center_y; $i--) { $arcStart = 0; foreach ($this->pie_data_array_percents as $key => $value) { $color = $this->generateNextColor(true); //GENERATE A DARKER VERSION OF THE INDEXED COLOR imagefilledarc($this->image, $this->pie_center_x, $i, $this->pie_width, $this->pie_height, $arcStart, (360 * $value) + $arcStart, $color, IMG_ARC_PIE); $arcStart += 360*$value; } $this->resetColorPointer(); } $arcStart = 0; foreach ($this->pie_data_array_percents as $key => $value) { $color = $this->generateNextColor(); imagefilledarc($this->image, $this->pie_center_x, $this->pie_center_y, $this->pie_width, $this->pie_height, $arcStart, (360*$value)+$arcStart, $color, IMG_ARC_PIE); if ($this->bool_data_labels) { $this->generateDataLabel($value, $arcStart); } $arcStart += 360 * $value; } } function generateDataLabel($value, $arcStart) { //MIDWAY IF THE MID ARC ANGLE OF THE WEDGE WE JUST DREW $midway = ($arcStart + (360 * $value) + $arcStart) / 2; //ADJUST FOR ELLIPSE HEIGHT/WIDTH RATIO $skew = $this->pie_height_percent / $this->pie_width_percent; $pi = atan(1.0) * 4.0; $theta = ($midway / 180) * $pi; $valueX = $this->pie_center_x + ($this->pie_width / 2 + $this->pie_data_label_space) * cos($theta); $valueY = $this->pie_center_y + ($this->pie_width / 2 + $this->pie_data_label_space) * sin($theta) * $skew; $displayValue = $this->formatPercent($value); $valueArray = $this->dataLabelHandicap($valueX, $valueY, $displayValue, $midway); $valueX = $valueArray[0]; $valueY = $valueArray[1]; imagestring($this->image, 2, $valueX, $valueY, $displayValue, $this->label_text_color); } function formatPercent($input) { return number_format($input * 100, $this->pie_precision) . '%'; } function dataLabelHandicap($x, $y, $value, $midway) { //MOVES DATA LABEL X/Y BASED ON QUADRANT AND LENGTH OF DISPLAYED DATA //AND HOW TEXT IS DISPLAYED (UPPER LEFT CORNER X/Y) //EXTRA 1 FOR % SIGN $lengthOffset = (strlen($value) * ($this->pie_label_text_width)) / 2; $vertOffset = $this->pie_label_text_height / 2; if ($midway <= 30) { $newX = $x - (1.5 * $lengthOffset); $newY = $y - $vertOffset; } else if ($midway > 30 && $midway <= 135) { $newX = $x - $lengthOffset; $newY = $y - $vertOffset + $this->pie_3D_height; } else if ($midway > 135 && $midway <= 165) { $newX = $x - $lengthOffset; $newY = $y - $vertOffset; } else if ($midway > 165 && $midway <= 200) { //VALUE AT RISK FOR BEING OUT OF BOUNDS ON SMALLER GRAPHS $newX = $x - (1/3 * $lengthOffset); $newY = $y - $vertOffset; } else if ($midway > 200 && $midway <= 330) { $newX = $x - $lengthOffset; $newY = $y - $vertOffset; } else if ($midway > 330) { //VALUE AT RISK FOR OVERLAPPING THE LEGEND ON SMALLER GRAPHS $newX = $x - (1.5 * $lengthOffset); $newY = $y - $vertOffset; } else { $newX = $x - $lengthOffset; $newY = $y - $vertOffset; } return array($newX, $newY); } function generateNextColor($dark = false) { $array = $this->returnColorArray($this->pie_avail_colors[$this->pie_color_pointer]); if ($dark) { //WE ARE TRYING TO GENERATE A DARKER VERSION OF THE EXISTING COLOR $array[0] *= .8; $array[1] *= .8; $array[2] *= .8; } $color = imagecolorallocate($this->image, $array[0], $array[1], $array[2]); $this->pie_color_pointer++; if ($this->pie_color_pointer >= count($this->pie_avail_colors)) { $this->pie_color_pointer = 0; } return $color; } function resetColorPointer() { $this->pie_color_pointer = 0; } function returnColorArray($color) { //THIS FUNCTION FIRST CHECKS EXISITNG COLORS IN PHPGraphLib //THEN IF NOT FOUND CHECKS ITS OWN LIST //COMES WITH VARIOUS PRESET LIGHTER PIE CHART FRIENDLY COLORS if ($resultColor = PHPGraphLib::returnColorArray($color)) { return $resultColor; } else { //REMOVE LAST ERROR GENERATED (PHPGraphLib::returnColorArray) SETS ONLY ONE ERROR IF FALSE) array_pop($this->error); //CHECK TO SEE IF NUMERIC COLOR PASSED THROUGH IN FORM '128,128,128' if (strpos($color,',') !== false) { return explode(',', $color); } switch(strtolower($color)) { //NAMED COLORS BASED ON W3C's RECOMMENDED HTML COLORS case 'pastel_orange_1': return array(238,197,145); break; case 'pastel_orange_2': return array(238,180,34); break; case 'pastel_blue_1': return array(122,197,205); break; case 'pastel_green_1': return array(102,205,0); break; case 'pastel_blue_2': return array(125,167,217); break; case 'pastel_green_2': return array(196,223,155); break; case 'clay': return array(246,142,85); break; case 'pastel_yellow': return array(255,247,153); break; case 'pastel_purple': return array(135,129,189); break; case 'brown': return array(166,124,81); break; } $this->error[] = "Color name \"$color\" not recogized."; return false; } } function generateTitle() { //DRAWS TITLE B/T TOP OF GRAPH AND EDGE OF CANVAS $pieTop = $this->pie_center_y - ($this->pie_height / 2); if ($this->bool_legend) { $topElement = ($pieTop < $this->pie_legend_y) ? $pieTop : $this->pie_legend_y; } else { $topElement = $pieTop; } if ($topElement < 0) { $this->error[] = "Not enough room for a title. Increase graph height, or eliminate data values."; } else { $title_y = ($topElement / 2) - ($this->title_char_height / 2); $title_x = ($this->width / 2) - ((strlen($this->title_text) * $this->title_char_width) / 2); imagestring($this->image, 2, $title_x , $title_y , $this->title_text, $this->title_color); } } //"PUBLIC" CUSTOMIZATION FUNCTIONS function setLabelTextColor($color) { $this->setGenericColor($color, '$this->label_text_color', "Label text color not specified properly."); } function setPrecision($digits) { if (is_int($digits)) { $this->pie_precision = $digits;} else { $this->error[] = "Integer arg for setPrecision() not specified properly."; } } function setDataLabels($bool) { if (is_bool($bool)) { $this->bool_data_labels = $bool;} else { $this->error[] = "Boolean arg for setDataLabels() not specified properly."; } } //UNUSED PHPGRAPHLIB FUNCTIONS OVERWRITTEN function generateXAxis(){} function generateYAxis(){} function setupXAxis(){} function setupYAxis(){} function calcTopMargin(){} function calcRightMargin(){} function generateDataPoints(){} } ?>
|