Accueil > > > AMÉLIORATION : CAMEMBERT
AMÉLIORATION : CAMEMBERT
Information sur la source
Description
Bonjour à tous
Je viens de développer un camembert 2D dans le but de m'entrainer, mais aussi de ressembler au mieux à celui généré par Flex 4 (j'ai un projet sous Flex 4 et j'ai un module d'impression PDF qui doit rendre le même résultat que Flex 4, d'où la nécessité de coder le mien, les autres ayant à chaque fois au moins un détail gênant qui diffère).
J'aimerais vos avis et suggestions sur ce qui a été fait. :)
Il s'agit d'une version 1, et plusieurs améliorations sont à venir:
- explodeSlice(): pour détacher un morceau du reste du camembert (mise en retrait)
- drawVLegend(): contrairement à drawHLegend() qui dessine la légende horizontalement à la base, celui-ci les dessinera à gauche ou à droite et verticalement
- set3D(): pour une version 3D du camembert
- et d'autres encore
Le point où j'aimerais aussi avoir part de vos idées, c'est celui pour rendre le graphique plus joli (éviter de voir les pixels).
J'ai essayé d'appliquer l'antialiasing, mais soit je ne m'en sers pas correctement, soit il est inefficace ici...
Ci-dessous:
- AKPie.php : la classe du graphique
- test.php : un exemple d'utilisation
- et il faudra inclure "font.ttf" qui n'est autre que la police courrier par défaut dans C:\Windows\Font\ (pour windows)
Voilà :)
Et merci à ceux qui auront le courage de lire, voire de tester ;)
Source
- // --- test.php -----------------------------------------------
- include 'AKPie.php';
-
- // --- Call example
- // test.php?seriesX=a:11:{s:10:%22Logistique%22;s:2:%2216%22;s:18:%22Cabinet%20de%20conseil%22;s:1:%227%22;s:14:%22Pharmaceutique%22;s:1:%227%22;s:10:%22Automobile%22;s:1:%227%22;s:28:%22SSII%20et%20Conseil%20Informatique%22;s:1:%227%22;s:8:%22T%E9l%E9coms%22;s:1:%227%22;s:55:%22Administration%20d%27Etat,%20Poste,%20Collectivit%E9%20Territoriale%22;s:1:%224%22;s:8:%22B%E2timent%22;s:1:%223%22;s:6:%22M%E9dias%22;s:1:%223%22;s:9:%22Industrie%22;s:1:%223%22;s:5:%22Autre%22;s:1:%227%22;}
- // test.php?seriesX=a:3:{i:0;i:2009;i:1;i:2010;i:2;i:2011;}&seriesY=a:3:{i:0;i:118;i:1;i:218;i:2;i:780;}
-
- // --- Data retrieving
- $seriesX = (!empty($_GET['seriesX']))
- ? unserialize(stripslashes($_GET['seriesX']))
- : array();
- $seriesY = (!empty($_GET['seriesY']))
- ? unserialize(stripslashes($_GET['seriesY']))
- : array();
-
- // --- Class instanciation
- $pie = new AKPie($seriesX, $seriesY);
- $pie->draw();
-
-
- // --- AKPie.php ---------------------------------------------------------------------------------------
- <?php
- /* ------------------------------------------------------------ *
- * ___ ___ *
- * / // / *
- * / // / __ __ *
- * / // \ / /__ __ __ __/ /_ _ _ _ __ ____ *
- * / /| |\ \ __ __ / //_/ _//_ |/_ __/_/ \/ _ |/ _/ *
- * / /_| | \ \ . \ . \ // / /_/ . | / / / / / / / | /\_ \ *
- * /________| \__\ _/ _///_/\__/\__|_\\_//_/\__/_/ /_/____/ *
- * / / / / *
- * /_/ /_/ *
- * *
- * ------------------------------------------------------------ *
- * Class: AKPie *
- * *
- * @author: Asph@tor (under Advanced Partner's project) *
- * @date: 2011-05-17 *
- * @version: v1.0.0 *
- * @compatible: PHP >= 4.2 *
- * @dependancies: GD2 *
- * font.ttf *
- * @license: free of use, of modifications and of *
- * commercialization. Just past this header *
- * at the begining of your code *
- * @contact: akpplications@gmail.com *
- * ------------------------------------------------------------ */
-
- class AKPie {
- protected $img; // The chart instance (true colors)
- protected $antialias; // Antialiasing
- protected $backgroundColor; // Background color behind the chart
- protected $borderColor; // Chart border's color
- protected $pieBorderColor; // Pie border's color
- protected $pieDelta; // Distance between pie and legend's labels
- protected $piePadding; // Chart's padding
- protected $pieX; // Chart's origin x value
- protected $pieY; // Chart's origin y value
- protected $pieSize; // Chart's size
- protected $width; // Display area width
- protected $height; // Display area height
- protected $title; // Chart's title
- protected $titleColor; // Chart title's color
- protected $titleFont; // Chart title's font to use
- protected $titlePadding; // Chart title's distance from the nearest side
- protected $titleSize; // Chart title's size
- protected $legendLabelColor; // Legend item label's color
- protected $legendLabelGap; // Gap between legend's labels
- protected $legendLabelSize; // Legend item label's size
- protected $legendPadding; // Legend box's distance from the nearest side
- protected $legendPosition; // Legend position (left, bottom, right, top)
- protected $legendWidth; // Legend width
- protected $guidLabelSize; // Legend guid label's size
- protected $guidLinesColor; // Legend guid line's color
- protected $guidLabelsColor; // Legend guid label's color
- protected $seriesX; // Data keys' label
- protected $seriesY; // Data values' label
- protected $seriesZ; // Data values in percents
- protected $precision; // Percents precision
- protected $showBorder; // Show chart's borders
- protected $showLegend; // Show legend
- protected $showLegendBorder; // Show legend's border
- protected $showPieBorder; // Show pie's and slices' border
- protected $showShadow; // Show pie's shadow
- protected $showGuidLines; // Show lines between slices and slices' label
- protected $showGuidLabels; // Show slices' labels
- protected $titleY; // First free y after title's drawing
- protected $legendY; // Last free y after legend's drawing
- protected $slicesColors; // Chart's color range
- protected $shadowColor; // Pie shadow's color
- protected $shadowLagX; // Pie shadow's x distance from pie
- protected $shadowLagY; // Pie shadow's y distance from pie
-
- // ---------------------------------------------------------
- // --- CONSTRUCTOR ---
- // ---------------------------------------------------------
-
- function __construct($seriesX=array(), $seriesY=array()) {
- if (count($seriesY) == 0) {
- $this->seriesX = array_keys($seriesX);
- $this->seriesY = array_values($seriesX);
- } else if (count($seriesX) == 0 || count($seriesY) != count($seriesX)) {
- echo "ERROR: incorrect parameters - size of each parameters should be the same!";
- } else {
- $this->seriesX = array_values($seriesX);
- $this->seriesY = array_values($seriesY);
- }
-
- $this->width = 800;
- $this->height = 600;
- $this->precision = 2;
- $this->antialias = true;
- $this->title = 'My Pie Chart';
- $this->titleColor = '333333';
- $this->titleFont = 'font.ttf';
- $this->titlePadding = 40;
- $this->titleSize = 16;
- $this->titleY = 0;
- $this->backgroundColor = '#FFFFFF';
- $this->borderColor = '0x444444';
- $this->legendY = $this->height;
- $this->legendLabelColor = 'ff0';
- $this->legendLabelSize = 8;
- $this->legendLabelGap = $this->legendLabelSize*3/4;
- $this->legendPadding = 20;
- $this->legendPosition = 'bottom';
- $this->legendWidth = 250;
- $this->guidLabelSize = 8;
- $this->guidLinesColor = '0x444444';
- $this->guidLabelsColor = '0x444444';
- $this->pieBorderColor = 'ccc';
- $this->pieDelta = 20;
- $this->piePadding = 0;
- $this->showBorder = true;
- $this->showLegend = true;
- $this->showLegendBorder = true;
- $this->showPieBorder = true;
- $this->showShadow = true;
- $this->showGuidLines = true;
- $this->showGuidLabels = true;
- $this->shadowColor = '444';
- $this->shadowLagX = 3;
- $this->shadowLagY = 3;
- $this->slicesColors = array(
- '0xE48701', '0x1B85D9', '0xA5BC4E', '0xFFFC93', '0x7ECFE1',
- '0xFF84BC', '0xC5F57E', '0x7EA6CE', '0xFF7E9F', '0x7EC29B',
- '0x7E83BB', '0xFFB17E', '0x7EC9BD', '0xC57EBF', '0xFFBD8A');
- }
-
- // ---------------------------------------------------------
- // --- SETTERS ---
- // ---------------------------------------------------------
-
- function setAntialias($antialias) { $this->antialias = $antialias; }
- function setBackgroundColor($color) { $this->backgroundColor = $color; }
- function setBorderColor($color) { $this->borderColor = $color; }
- function setPieBorderColor($color) { $this->pieBorderColor = $color; }
- function setPieDelta($delta) { $this->pieDelta = $delta; }
- function setPiePadding($padding) { $this->piePadding = $padding; }
- function setWidth($width) { $this->width = $width; }
- function setHeight($height) { $this->height = $height; }
- function setTitle($title) { $this->title = $title; }
- function setTitleFont($font) { $this->titleFont = $font; }
- function setTitleColor($color) { $this->titleColor = $color; }
- function setTitleSize($size) { $this->titleSize = $size; }
- function setTitlePadding($padding) { $this->titlePadding = $padding; }
- function setLabelFunction($function) { $this->labelFunction = $function; }
- function setLegendWidth($width) { $this->legendWidth = $width; }
- function setLegendLabelColor($color) { $this->legendLabelColor = $color; }
- function setLegendLabelGap($gap) { $this->legendLabelGap = $gap; }
- function setLegendLabelSize($size) { $this->legendLabelSize = $size;
- $this->legendLabelGap = $size*3/4; }
- function setLegendPadding($padding) { $this->legendPadding = $padding; }
- function setLegendPosition($position) { $this->legendPosition = $position; }
- function setGuidLabelSize($size) { $this->guidLabelSize = $size; }
- function setGuidLabelsColor($color) { $this->guidLabelsColor = $color; }
- function setGuidLinesColor($color) { $this->guidLinesColor = $color; }
- function setPrecision($precision) { $this->precision = $precision; }
- function showBorder() { $this->showBorder = true; }
- function showLegend() { $this->showLegend = true; }
- function showLegendBorder() { $this->showLegendBorder = true; }
- function showPieBorder() { $this->showPieBorder = true; }
- function showShadow() { $this->showShadow = true; }
- function showGuidLines() { $this->showGuidLines = true; }
- function showGuidLabels() { $this->showGuidLabels = true; }
- function setSlicesColors($colors) { $this->slicesColors = $colors; }
- function setShadowColor($color) { $this->shadowColor = $color; }
- function setShadowLagX($lag) { $this->shadowLagX = $lag; }
- function setShadowLagY($lag) { $this->shadowLagY = $lag; }
-
- // ---------------------------------------------------------
- // --- PUBLIC METHODS ---
- // ---------------------------------------------------------
-
- function draw() {
- $this->img = imagecreatetruecolor($this->width, $this->height);
- imageantialias($this->img, $this->antialias);
-
- $this->drawBackground();
- $this->drawBorder();
- $this->drawTitle();
- $this->drawHLegend();
- $this->drawPie();
- $this->drawGuidLines();
-
- header('Content-Type: image/png');
- imagepng($this->img);
- imagedestroy($this->img);
- }
-
- // ---------------------------------------------------------
- // --- PRIVATE METHODS ---
- // ---------------------------------------------------------
-
- protected function calculatePercents($data) {
- $percents = array();
- $len = count($data);
- $total = 0;
-
- foreach ($data as $v)
- $total+=$v;
- foreach ($data as $v)
- $percents[] = round($v * 100 / $total, $this->precision);
-
- return $percents;
- }
-
- protected function formatGuidLabel($label, $width) {
- $str = explode(' ', $label);
- $len = count($str);
- $line = 1;
- $txt = $str[0];
- $label = '';
- $maxWidth = 0;
-
- for ($i=1; $i<$len; $i++) {
- if (strlen($txt.' '.$str[$i])*$this->guidLabelSize*3/4 < $width)
- $txt .= ' '.$str[$i];
- else {
- $w = strlen($txt)*$this->guidLabelSize*3/4;
- if ($maxWidth < $w)
- $maxWidth = $w;
- $label .= $txt."\n";
- $txt = $str[$i];
- $line++;
- }
- }
- $label .= $txt;
-
- return array($label, $line, $maxWidth);
- }
-
- protected function drawBackground() {
- list($r, $g, $b) = $this->html2rgb($this->backgroundColor);
- $bgcolor = imagecolorallocate($this->img, $r, $g, $b);
- imagefilledrectangle($this->img, 0, 0, $this->width-1, $this->height-1, $bgcolor);
- }
-
- protected function drawBorder() {
- if ($this->showBorder) {
- list($r, $g, $b) = $this->html2rgb($this->borderColor);
- $bgcolor = imagecolorallocate($this->img, $r, $g, $b);
- imagerectangle($this->img, 0, 0, $this->width-1, $this->height-1, $bgcolor);
- }
- }
-
- protected function drawTitle() {
- // POSSIBLE OPTIMIZATION: word wrapping
- $x = ($this->width - (strlen($this->title) * $this->titleSize*5/6)) / 2;
- $y = $this->titlePadding;
- list($r, $g, $b) = $this->html2rgb($this->titleColor);
- $titleColor = imagecolorallocate($this->img, $r, $g, $b);
- imagettftext($this->img, $this->titleSize, 0, $x, $y, $titleColor, $this->titleFont, $this->title);
- $this->titleY = $y + $this->titlePadding;
- }
-
- protected function drawHLegend() {
- if ($this->showLegend) {
- // box sizes and paddings
- $cellSize = $this->legendLabelSize * 0.75;
- $textSize = $this->legendLabelSize;
- $cellPadding = ($textSize - $cellSize) / 2;
-
- // lengths and item/line numbers
- $len = count($this->seriesX);
- $max = 0;
- $nb = 0;
- $flag = $this->width - 2*$this->legendPadding;
-
- // colors
- $slices = count($this->slicesColors);
- list($r, $g, $b) = $this->html2rgb($this->borderColor);
- $borderColor = imagecolorallocate($this->img, $r, $g, $b);
-
- // longest label width
- for ($i=0; $i<$len; $i++)
- if (strlen($this->seriesX[$i]) > strlen($this->seriesX[$max]))
- $max = $i;
- $wordWidth = strlen($this->seriesX[$max]) * $textSize;
-
- // number of lines and items per line
- $cellWidth = 3*$cellSize + $wordWidth;
- $cellHeight = $textSize + $cellSize;
- while ($flag > 0 && $nb < $len) {
- $flag -= $cellWidth;
- $nb++;
- }
- if ($cellWidth * $nb > $this->width - $this->legendPadding*2)
- $nb--;
- $line = ceil($len / $nb);
-
- // positions
- switch ($this->legendPosition) {
- case "top":
- $x = ($this->width - $nb*$cellWidth) / 2;
- $y = $this->titleY;
- $this->legendY = $this->height;
- break;
- case "bottom":
- default:
- $x = ($this->width - $nb*$cellWidth) / 2 ;
- $y = $this->height - ($textSize+$this->legendLabelGap)*$line - $this->legendPadding;
- $this->legendY = $y - $this->legendPadding;
- break;
- }
-
- // draw items
- for ($i=0; $i<$line; $i++) {
- for ($j=0; $j<$nb && $j<$len-$i*$nb; $j++) {
- // draw color cell
- list($r, $g, $b) = $this->html2rgb($this->slicesColors[($i*$nb+$j)%$slices]);
- $legendColor = imagecolorallocate($this->img, $r, $g, $b);
- imagefilledrectangle(
- $this->img,
- $x+1+$j*$cellWidth,
- $y+$cellPadding+1+$i*$cellHeight,
- $x+$cellSize-2+$j*$cellWidth,
- $y+$cellPadding+$cellSize-2+$i*$cellHeight,
- $legendColor);
- imagerectangle(
- $this->img,
- $x+$j*$cellWidth,
- $y+$cellPadding+$i*$cellHeight,
- $x+$cellSize-1+$j*$cellWidth,
- $y+$cellPadding+$cellSize-1+$i*$cellHeight,
- $borderColor);
-
- // draw label
- imagettftext(
- $this->img,
- $textSize,
- 0,
- $x+2*$cellSize+$j*$cellWidth,
- $y+$textSize-1+$i*$cellHeight,
- $titleColor,
- $this->titleFont,
- $this->seriesX[$i*$nb+$j]);
- }
- }
-
- // draw border
- if ($this->showLegendBorder)
- imagerectangle(
- $this->img,
- $x-$this->legendPadding/2,
- $y-$this->legendPadding/2,
- $x+$nb*$cellWidth,
- $y+$line*$cellHeight,
- $borderColor);
-
- if ($this->legendPosition == 'top')
- $this->titleY = $y+$line*$cellHeight+$this->legendPadding;
- }
- }
-
- protected function drawPie() {
- // position
- $x = $this->width / 2;
- $y = ($this->titleY + $this->legendY) / 2;
- $pieSize = $this->height - ($this->titleY + $this->height - $this->legendY + 2*$this->piePadding);
- $pieSize *= 3/5;
- $this->pieX = $x;
- $this->pieY = $y;
- $this->pieSize = $pieSize;
-
- // shadow
- if ($this->showShadow) {
- list($r, $g, $b) = $this->html2rgb($this->shadowColor);
- $color = imagecolorallocate($this->img, $r, $g, $b);
- imagefilledarc($this->img, $x+$this->shadowLagX, $y+$this->shadowLagY, $pieSize, $pieSize, 0, 360, $color, IMG_ARC_PIE);
- }
-
- // calculate percents
- $this->seriesZ = $this->calculatePercents($this->seriesY);
-
- // slices drawing
- $len = count($this->seriesX);
- $slen = count($this->slicesColors);
- list($r, $g, $b) = $this->html2rgb($this->pieBorderColor);
- $borderColor = imagecolorallocate($this->img, $r, $g, $b);
- $deg = 0;
- for ($i=0; $i<$len; $i++) {
- list($r, $g, $b) = $this->html2rgb($this->slicesColors[$i%$slen]);
- $color = imagecolorallocate($this->img, $r, $g, $b);
- $end = ($i==$len-1) ? 360 : $deg + $this->seriesZ[$i] * 360 / 100;
- imagefilledarc($this->img, $x, $y, $pieSize, $pieSize, $deg, $end, $color, IMG_ARC_PIE);
- if ($this->showPieBorder)
- imagefilledarc($this->img, $x, $y, $pieSize, $pieSize, $deg, $end, $borderColor, IMG_ARC_EDGED | IMG_ARC_NOFILL);
- $deg = $end;
- }
-
- // IMG_ARC_PIE | IMG_ARC_EDGED | IMG_ARC_NOFILL | IMG_ARC_CHORD
- }
-
- protected function drawGuidLines() {
- if ($this->showGuidLabels) {
- // data retrieving
- $x = $this->pieX;
- $y = $this->pieY;
- $d = $this->pieSize/2;
- $xl = $x - ($d + $this->pieDelta);
- $xr = $x + ($d + $this->pieDelta);
- list($r, $g, $b) = $this->html2rgb($this->guidLinesColor);
- $color = imagecolorallocate($this->img, $r, $g, $b);
-
- // drawing
- $deg = 0; $v = $this->seriesZ[0];
- foreach ($this->seriesZ as $k => $v) {
- $tmp = ($v*2*pi()/100);
-
- // lines
- $xx = ($x + ($d + $this->pieDelta)*cos($deg + $tmp/2)) > $x ? $xr : $xl;
- if ($this->showGuidLines) {
- imageline(
- $this->img,
- $x + ($d - $this->pieDelta)*cos($deg + $tmp/2),
- $y + ($d - $this->pieDelta)*sin($deg + $tmp/2),
- $x + ($d + $this->pieDelta)*cos($deg + $tmp/2),
- $y + ($d + $this->pieDelta)*sin($deg + $tmp/2),
- $color);
- imageline(
- $this->img,
- $x + ($d + $this->pieDelta)*cos($deg + $tmp/2),
- $y + ($d + $this->pieDelta)*sin($deg + $tmp/2),
- $xx,
- $y + ($d + $this->pieDelta)*sin($deg + $tmp/2),
- $color);
- }
-
- // labels
- if ($xx == $xr) {
- list($txt, $nb, $w) = $this->formatGuidLabel($this->seriesX[$k], $this->width - $xr - $this->pieDelta);
- $xx = $xr + $this->pieDelta;
- } else {
- $width = strlen($this->seriesX[$k])*$this->guidLabelSize*3/4;
- list($txt, $nb, $w) = $this->formatGuidLabel($this->seriesX[$k], $xl - $this->pieDelta);
- $xx = $xl - $this->pieDelta - ($nb > 1 ? $w : $width);
- }
-
- imagettftext(
- $this->img,
- $this->guidLabelSize,
- 0,
- $xx,
- $y + ($d+$this->pieDelta)*sin($deg+$tmp/2) + $this->guidLabelSize/2 - ($nb-1)*$this->guidLabelSize/2,
- $this->guidLabelsColor,
- $this->titleFont,
- $txt);
-
- $deg += $tmp;
- }
- }
- }
-
- // ---------------------------------------------------------
- // --- STATIC METHODS ---
- // ---------------------------------------------------------
-
- static function html2rgb($color) {
- if ($color[0] == '#')
- $color = substr($color, 1);
-
- if ($color[0] == '0' && $color[1] == 'x')
- $color = substr($color, 2);
-
- if (strlen($color) == 6)
- return array(
- hexdec($color[0].$color[1]),
- hexdec($color[2].$color[3]),
- hexdec($color[4].$color[5]));
-
- elseif (strlen($color) == 3)
- return array(
- hexdec($color[0].$color[0]),
- hexdec($color[1].$color[1]),
- hexdec($color[2].$color[2]));
-
- else return false;
- }
-
- static function rgb2html($r, $g=-1, $b=-1) {
- if (is_array($r) && sizeof($r) == 3)
- list($r, $g, $b) = $r;
-
- $r = intval($r);
- $g = intval($g);
- $b = intval($b);
-
- $r = dechex($r < 0 ? 0 : ($r > 255 ? 255 : $r));
- $g = dechex($g < 0 ? 0 : ($g > 255 ? 255 : $g));
- $b = dechex($b < 0 ? 0 : ($b > 255 ? 255 : $b));
-
- $color = (strlen($r) < 2 ? '0' : '').$r;
- $color .= (strlen($g) < 2 ? '0' : '').$g;
- $color .= (strlen($b) < 2 ? '0' : '').$b;
-
- return '#'.$color;
- }
-
- }
-
- ?>
-
// --- test.php -----------------------------------------------
include 'AKPie.php';
// --- Call example
// test.php?seriesX=a:11:{s:10:%22Logistique%22;s:2:%2216%22;s:18:%22Cabinet%20de%20conseil%22;s:1:%227%22;s:14:%22Pharmaceutique%22;s:1:%227%22;s:10:%22Automobile%22;s:1:%227%22;s:28:%22SSII%20et%20Conseil%20Informatique%22;s:1:%227%22;s:8:%22T%E9l%E9coms%22;s:1:%227%22;s:55:%22Administration%20d%27Etat,%20Poste,%20Collectivit%E9%20Territoriale%22;s:1:%224%22;s:8:%22B%E2timent%22;s:1:%223%22;s:6:%22M%E9dias%22;s:1:%223%22;s:9:%22Industrie%22;s:1:%223%22;s:5:%22Autre%22;s:1:%227%22;}
// test.php?seriesX=a:3:{i:0;i:2009;i:1;i:2010;i:2;i:2011;}&seriesY=a:3:{i:0;i:118;i:1;i:218;i:2;i:780;}
// --- Data retrieving
$seriesX = (!empty($_GET['seriesX']))
? unserialize(stripslashes($_GET['seriesX']))
: array();
$seriesY = (!empty($_GET['seriesY']))
? unserialize(stripslashes($_GET['seriesY']))
: array();
// --- Class instanciation
$pie = new AKPie($seriesX, $seriesY);
$pie->draw();
// --- AKPie.php ---------------------------------------------------------------------------------------
<?php
/* ------------------------------------------------------------ *
* ___ ___ *
* / // / *
* / // / __ __ *
* / // \ / /__ __ __ __/ /_ _ _ _ __ ____ *
* / /| |\ \ __ __ / //_/ _//_ |/_ __/_/ \/ _ |/ _/ *
* / /_| | \ \ . \ . \ // / /_/ . | / / / / / / / | /\_ \ *
* /________| \__\ _/ _///_/\__/\__|_\\_//_/\__/_/ /_/____/ *
* / / / / *
* /_/ /_/ *
* *
* ------------------------------------------------------------ *
* Class: AKPie *
* *
* @author: Asph@tor (under Advanced Partner's project) *
* @date: 2011-05-17 *
* @version: v1.0.0 *
* @compatible: PHP >= 4.2 *
* @dependancies: GD2 *
* font.ttf *
* @license: free of use, of modifications and of *
* commercialization. Just past this header *
* at the begining of your code *
* @contact: akpplications@gmail.com *
* ------------------------------------------------------------ */
class AKPie {
protected $img; // The chart instance (true colors)
protected $antialias; // Antialiasing
protected $backgroundColor; // Background color behind the chart
protected $borderColor; // Chart border's color
protected $pieBorderColor; // Pie border's color
protected $pieDelta; // Distance between pie and legend's labels
protected $piePadding; // Chart's padding
protected $pieX; // Chart's origin x value
protected $pieY; // Chart's origin y value
protected $pieSize; // Chart's size
protected $width; // Display area width
protected $height; // Display area height
protected $title; // Chart's title
protected $titleColor; // Chart title's color
protected $titleFont; // Chart title's font to use
protected $titlePadding; // Chart title's distance from the nearest side
protected $titleSize; // Chart title's size
protected $legendLabelColor; // Legend item label's color
protected $legendLabelGap; // Gap between legend's labels
protected $legendLabelSize; // Legend item label's size
protected $legendPadding; // Legend box's distance from the nearest side
protected $legendPosition; // Legend position (left, bottom, right, top)
protected $legendWidth; // Legend width
protected $guidLabelSize; // Legend guid label's size
protected $guidLinesColor; // Legend guid line's color
protected $guidLabelsColor; // Legend guid label's color
protected $seriesX; // Data keys' label
protected $seriesY; // Data values' label
protected $seriesZ; // Data values in percents
protected $precision; // Percents precision
protected $showBorder; // Show chart's borders
protected $showLegend; // Show legend
protected $showLegendBorder; // Show legend's border
protected $showPieBorder; // Show pie's and slices' border
protected $showShadow; // Show pie's shadow
protected $showGuidLines; // Show lines between slices and slices' label
protected $showGuidLabels; // Show slices' labels
protected $titleY; // First free y after title's drawing
protected $legendY; // Last free y after legend's drawing
protected $slicesColors; // Chart's color range
protected $shadowColor; // Pie shadow's color
protected $shadowLagX; // Pie shadow's x distance from pie
protected $shadowLagY; // Pie shadow's y distance from pie
// ---------------------------------------------------------
// --- CONSTRUCTOR ---
// ---------------------------------------------------------
function __construct($seriesX=array(), $seriesY=array()) {
if (count($seriesY) == 0) {
$this->seriesX = array_keys($seriesX);
$this->seriesY = array_values($seriesX);
} else if (count($seriesX) == 0 || count($seriesY) != count($seriesX)) {
echo "ERROR: incorrect parameters - size of each parameters should be the same!";
} else {
$this->seriesX = array_values($seriesX);
$this->seriesY = array_values($seriesY);
}
$this->width = 800;
$this->height = 600;
$this->precision = 2;
$this->antialias = true;
$this->title = 'My Pie Chart';
$this->titleColor = '333333';
$this->titleFont = 'font.ttf';
$this->titlePadding = 40;
$this->titleSize = 16;
$this->titleY = 0;
$this->backgroundColor = '#FFFFFF';
$this->borderColor = '0x444444';
$this->legendY = $this->height;
$this->legendLabelColor = 'ff0';
$this->legendLabelSize = 8;
$this->legendLabelGap = $this->legendLabelSize*3/4;
$this->legendPadding = 20;
$this->legendPosition = 'bottom';
$this->legendWidth = 250;
$this->guidLabelSize = 8;
$this->guidLinesColor = '0x444444';
$this->guidLabelsColor = '0x444444';
$this->pieBorderColor = 'ccc';
$this->pieDelta = 20;
$this->piePadding = 0;
$this->showBorder = true;
$this->showLegend = true;
$this->showLegendBorder = true;
$this->showPieBorder = true;
$this->showShadow = true;
$this->showGuidLines = true;
$this->showGuidLabels = true;
$this->shadowColor = '444';
$this->shadowLagX = 3;
$this->shadowLagY = 3;
$this->slicesColors = array(
'0xE48701', '0x1B85D9', '0xA5BC4E', '0xFFFC93', '0x7ECFE1',
'0xFF84BC', '0xC5F57E', '0x7EA6CE', '0xFF7E9F', '0x7EC29B',
'0x7E83BB', '0xFFB17E', '0x7EC9BD', '0xC57EBF', '0xFFBD8A');
}
// ---------------------------------------------------------
// --- SETTERS ---
// ---------------------------------------------------------
function setAntialias($antialias) { $this->antialias = $antialias; }
function setBackgroundColor($color) { $this->backgroundColor = $color; }
function setBorderColor($color) { $this->borderColor = $color; }
function setPieBorderColor($color) { $this->pieBorderColor = $color; }
function setPieDelta($delta) { $this->pieDelta = $delta; }
function setPiePadding($padding) { $this->piePadding = $padding; }
function setWidth($width) { $this->width = $width; }
function setHeight($height) { $this->height = $height; }
function setTitle($title) { $this->title = $title; }
function setTitleFont($font) { $this->titleFont = $font; }
function setTitleColor($color) { $this->titleColor = $color; }
function setTitleSize($size) { $this->titleSize = $size; }
function setTitlePadding($padding) { $this->titlePadding = $padding; }
function setLabelFunction($function) { $this->labelFunction = $function; }
function setLegendWidth($width) { $this->legendWidth = $width; }
function setLegendLabelColor($color) { $this->legendLabelColor = $color; }
function setLegendLabelGap($gap) { $this->legendLabelGap = $gap; }
function setLegendLabelSize($size) { $this->legendLabelSize = $size;
$this->legendLabelGap = $size*3/4; }
function setLegendPadding($padding) { $this->legendPadding = $padding; }
function setLegendPosition($position) { $this->legendPosition = $position; }
function setGuidLabelSize($size) { $this->guidLabelSize = $size; }
function setGuidLabelsColor($color) { $this->guidLabelsColor = $color; }
function setGuidLinesColor($color) { $this->guidLinesColor = $color; }
function setPrecision($precision) { $this->precision = $precision; }
function showBorder() { $this->showBorder = true; }
function showLegend() { $this->showLegend = true; }
function showLegendBorder() { $this->showLegendBorder = true; }
function showPieBorder() { $this->showPieBorder = true; }
function showShadow() { $this->showShadow = true; }
function showGuidLines() { $this->showGuidLines = true; }
function showGuidLabels() { $this->showGuidLabels = true; }
function setSlicesColors($colors) { $this->slicesColors = $colors; }
function setShadowColor($color) { $this->shadowColor = $color; }
function setShadowLagX($lag) { $this->shadowLagX = $lag; }
function setShadowLagY($lag) { $this->shadowLagY = $lag; }
// ---------------------------------------------------------
// --- PUBLIC METHODS ---
// ---------------------------------------------------------
function draw() {
$this->img = imagecreatetruecolor($this->width, $this->height);
imageantialias($this->img, $this->antialias);
$this->drawBackground();
$this->drawBorder();
$this->drawTitle();
$this->drawHLegend();
$this->drawPie();
$this->drawGuidLines();
header('Content-Type: image/png');
imagepng($this->img);
imagedestroy($this->img);
}
// ---------------------------------------------------------
// --- PRIVATE METHODS ---
// ---------------------------------------------------------
protected function calculatePercents($data) {
$percents = array();
$len = count($data);
$total = 0;
foreach ($data as $v)
$total+=$v;
foreach ($data as $v)
$percents[] = round($v * 100 / $total, $this->precision);
return $percents;
}
protected function formatGuidLabel($label, $width) {
$str = explode(' ', $label);
$len = count($str);
$line = 1;
$txt = $str[0];
$label = '';
$maxWidth = 0;
for ($i=1; $i<$len; $i++) {
if (strlen($txt.' '.$str[$i])*$this->guidLabelSize*3/4 < $width)
$txt .= ' '.$str[$i];
else {
$w = strlen($txt)*$this->guidLabelSize*3/4;
if ($maxWidth < $w)
$maxWidth = $w;
$label .= $txt."\n";
$txt = $str[$i];
$line++;
}
}
$label .= $txt;
return array($label, $line, $maxWidth);
}
protected function drawBackground() {
list($r, $g, $b) = $this->html2rgb($this->backgroundColor);
$bgcolor = imagecolorallocate($this->img, $r, $g, $b);
imagefilledrectangle($this->img, 0, 0, $this->width-1, $this->height-1, $bgcolor);
}
protected function drawBorder() {
if ($this->showBorder) {
list($r, $g, $b) = $this->html2rgb($this->borderColor);
$bgcolor = imagecolorallocate($this->img, $r, $g, $b);
imagerectangle($this->img, 0, 0, $this->width-1, $this->height-1, $bgcolor);
}
}
protected function drawTitle() {
// POSSIBLE OPTIMIZATION: word wrapping
$x = ($this->width - (strlen($this->title) * $this->titleSize*5/6)) / 2;
$y = $this->titlePadding;
list($r, $g, $b) = $this->html2rgb($this->titleColor);
$titleColor = imagecolorallocate($this->img, $r, $g, $b);
imagettftext($this->img, $this->titleSize, 0, $x, $y, $titleColor, $this->titleFont, $this->title);
$this->titleY = $y + $this->titlePadding;
}
protected function drawHLegend() {
if ($this->showLegend) {
// box sizes and paddings
$cellSize = $this->legendLabelSize * 0.75;
$textSize = $this->legendLabelSize;
$cellPadding = ($textSize - $cellSize) / 2;
// lengths and item/line numbers
$len = count($this->seriesX);
$max = 0;
$nb = 0;
$flag = $this->width - 2*$this->legendPadding;
// colors
$slices = count($this->slicesColors);
list($r, $g, $b) = $this->html2rgb($this->borderColor);
$borderColor = imagecolorallocate($this->img, $r, $g, $b);
// longest label width
for ($i=0; $i<$len; $i++)
if (strlen($this->seriesX[$i]) > strlen($this->seriesX[$max]))
$max = $i;
$wordWidth = strlen($this->seriesX[$max]) * $textSize;
// number of lines and items per line
$cellWidth = 3*$cellSize + $wordWidth;
$cellHeight = $textSize + $cellSize;
while ($flag > 0 && $nb < $len) {
$flag -= $cellWidth;
$nb++;
}
if ($cellWidth * $nb > $this->width - $this->legendPadding*2)
$nb--;
$line = ceil($len / $nb);
// positions
switch ($this->legendPosition) {
case "top":
$x = ($this->width - $nb*$cellWidth) / 2;
$y = $this->titleY;
$this->legendY = $this->height;
break;
case "bottom":
default:
$x = ($this->width - $nb*$cellWidth) / 2 ;
$y = $this->height - ($textSize+$this->legendLabelGap)*$line - $this->legendPadding;
$this->legendY = $y - $this->legendPadding;
break;
}
// draw items
for ($i=0; $i<$line; $i++) {
for ($j=0; $j<$nb && $j<$len-$i*$nb; $j++) {
// draw color cell
list($r, $g, $b) = $this->html2rgb($this->slicesColors[($i*$nb+$j)%$slices]);
$legendColor = imagecolorallocate($this->img, $r, $g, $b);
imagefilledrectangle(
$this->img,
$x+1+$j*$cellWidth,
$y+$cellPadding+1+$i*$cellHeight,
$x+$cellSize-2+$j*$cellWidth,
$y+$cellPadding+$cellSize-2+$i*$cellHeight,
$legendColor);
imagerectangle(
$this->img,
$x+$j*$cellWidth,
$y+$cellPadding+$i*$cellHeight,
$x+$cellSize-1+$j*$cellWidth,
$y+$cellPadding+$cellSize-1+$i*$cellHeight,
$borderColor);
// draw label
imagettftext(
$this->img,
$textSize,
0,
$x+2*$cellSize+$j*$cellWidth,
$y+$textSize-1+$i*$cellHeight,
$titleColor,
$this->titleFont,
$this->seriesX[$i*$nb+$j]);
}
}
// draw border
if ($this->showLegendBorder)
imagerectangle(
$this->img,
$x-$this->legendPadding/2,
$y-$this->legendPadding/2,
$x+$nb*$cellWidth,
$y+$line*$cellHeight,
$borderColor);
if ($this->legendPosition == 'top')
$this->titleY = $y+$line*$cellHeight+$this->legendPadding;
}
}
protected function drawPie() {
// position
$x = $this->width / 2;
$y = ($this->titleY + $this->legendY) / 2;
$pieSize = $this->height - ($this->titleY + $this->height - $this->legendY + 2*$this->piePadding);
$pieSize *= 3/5;
$this->pieX = $x;
$this->pieY = $y;
$this->pieSize = $pieSize;
// shadow
if ($this->showShadow) {
list($r, $g, $b) = $this->html2rgb($this->shadowColor);
$color = imagecolorallocate($this->img, $r, $g, $b);
imagefilledarc($this->img, $x+$this->shadowLagX, $y+$this->shadowLagY, $pieSize, $pieSize, 0, 360, $color, IMG_ARC_PIE);
}
// calculate percents
$this->seriesZ = $this->calculatePercents($this->seriesY);
// slices drawing
$len = count($this->seriesX);
$slen = count($this->slicesColors);
list($r, $g, $b) = $this->html2rgb($this->pieBorderColor);
$borderColor = imagecolorallocate($this->img, $r, $g, $b);
$deg = 0;
for ($i=0; $i<$len; $i++) {
list($r, $g, $b) = $this->html2rgb($this->slicesColors[$i%$slen]);
$color = imagecolorallocate($this->img, $r, $g, $b);
$end = ($i==$len-1) ? 360 : $deg + $this->seriesZ[$i] * 360 / 100;
imagefilledarc($this->img, $x, $y, $pieSize, $pieSize, $deg, $end, $color, IMG_ARC_PIE);
if ($this->showPieBorder)
imagefilledarc($this->img, $x, $y, $pieSize, $pieSize, $deg, $end, $borderColor, IMG_ARC_EDGED | IMG_ARC_NOFILL);
$deg = $end;
}
// IMG_ARC_PIE | IMG_ARC_EDGED | IMG_ARC_NOFILL | IMG_ARC_CHORD
}
protected function drawGuidLines() {
if ($this->showGuidLabels) {
// data retrieving
$x = $this->pieX;
$y = $this->pieY;
$d = $this->pieSize/2;
$xl = $x - ($d + $this->pieDelta);
$xr = $x + ($d + $this->pieDelta);
list($r, $g, $b) = $this->html2rgb($this->guidLinesColor);
$color = imagecolorallocate($this->img, $r, $g, $b);
// drawing
$deg = 0; $v = $this->seriesZ[0];
foreach ($this->seriesZ as $k => $v) {
$tmp = ($v*2*pi()/100);
// lines
$xx = ($x + ($d + $this->pieDelta)*cos($deg + $tmp/2)) > $x ? $xr : $xl;
if ($this->showGuidLines) {
imageline(
$this->img,
$x + ($d - $this->pieDelta)*cos($deg + $tmp/2),
$y + ($d - $this->pieDelta)*sin($deg + $tmp/2),
$x + ($d + $this->pieDelta)*cos($deg + $tmp/2),
$y + ($d + $this->pieDelta)*sin($deg + $tmp/2),
$color);
imageline(
$this->img,
$x + ($d + $this->pieDelta)*cos($deg + $tmp/2),
$y + ($d + $this->pieDelta)*sin($deg + $tmp/2),
$xx,
$y + ($d + $this->pieDelta)*sin($deg + $tmp/2),
$color);
}
// labels
if ($xx == $xr) {
list($txt, $nb, $w) = $this->formatGuidLabel($this->seriesX[$k], $this->width - $xr - $this->pieDelta);
$xx = $xr + $this->pieDelta;
} else {
$width = strlen($this->seriesX[$k])*$this->guidLabelSize*3/4;
list($txt, $nb, $w) = $this->formatGuidLabel($this->seriesX[$k], $xl - $this->pieDelta);
$xx = $xl - $this->pieDelta - ($nb > 1 ? $w : $width);
}
imagettftext(
$this->img,
$this->guidLabelSize,
0,
$xx,
$y + ($d+$this->pieDelta)*sin($deg+$tmp/2) + $this->guidLabelSize/2 - ($nb-1)*$this->guidLabelSize/2,
$this->guidLabelsColor,
$this->titleFont,
$txt);
$deg += $tmp;
}
}
}
// ---------------------------------------------------------
// --- STATIC METHODS ---
// ---------------------------------------------------------
static function html2rgb($color) {
if ($color[0] == '#')
$color = substr($color, 1);
if ($color[0] == '0' && $color[1] == 'x')
$color = substr($color, 2);
if (strlen($color) == 6)
return array(
hexdec($color[0].$color[1]),
hexdec($color[2].$color[3]),
hexdec($color[4].$color[5]));
elseif (strlen($color) == 3)
return array(
hexdec($color[0].$color[0]),
hexdec($color[1].$color[1]),
hexdec($color[2].$color[2]));
else return false;
}
static function rgb2html($r, $g=-1, $b=-1) {
if (is_array($r) && sizeof($r) == 3)
list($r, $g, $b) = $r;
$r = intval($r);
$g = intval($g);
$b = intval($b);
$r = dechex($r < 0 ? 0 : ($r > 255 ? 255 : $r));
$g = dechex($g < 0 ? 0 : ($g > 255 ? 255 : $g));
$b = dechex($b < 0 ? 0 : ($b > 255 ? 255 : $b));
$color = (strlen($r) < 2 ? '0' : '').$r;
$color .= (strlen($g) < 2 ? '0' : '').$g;
$color .= (strlen($b) < 2 ? '0' : '').$b;
return '#'.$color;
}
}
?>
Sources de la même categorie
Commentaires et avis
Discussions en rapport avec ce code source dans le forum
statistiques ,graphique, php et mysql [ par mouss ]
connaissez vous des exemples mettant en oeuvre une base de donnée mysql ,php permettant de créer des courbes, nuages de points sur une feuille html (p
Tableau 2D [ par goulouk ]
Bonjour je voudrais savoir comment créer et lire un tableau en 2D en php svp.merci.
graphique, histogramme, diagramme... [ par jbardet ]
Bonjour,Je souhaite créer des digramme de stat en php (+ exactement avec smarty) mais deja si j'y arrive en php ça le ferait!Mon problème:J'ai trouvé
Inclure un graphique généré dynamiquement ds une page html ou php [ par cjulie24 ]
CjulieHello,J'ai un p'tit souci et je suis à la recherche d'un bon samaritain !Voila, je suis en train de refaire un site et je dois inclure
Inclusion d'un graphique dynamique ds une page WEB [ par cjulie24 ]
CjulieHello,J'ai un p'tit souci et je suis à la recherche d'un bon samaritain !Voila, je suis en train de refaire un site et je dois inclure
Graphique php, imageTTFBBox et imageTTFText [ par DarkSchneider ]
salut tous le monde,C'est après deux et demi de bataille avec ce script que je vient déposer les armes ici. Le but de ce script a pour but de faire af
éditeur graphique html/php sous linux [ par eax ]
salutje ch un éditeur html, php, javascript graphique genre dreamweaver sous linux Sylvain [email] [<a href="http://www.ea
Php : le bon choix ? [ par Neglaus ]
Bonjour à tous voila ma question : je souhaite créer un module de gestion de statistique sous PHP avec des sorties sur graphiques. Mais attention il s
Php : ai je fais le bon choix?? [ par Neglaus ]
Bonjour à tous voila ma question : je souhaite créer un module de gestion de statistique sous PHP avec des sorties sur graphiques. Mais attention il s
conception d'un graphique boursier en php [ par jeremy77 ]
Bonjour, je suis a la recherche de sources pour la conception de graphique boursier en php comme ce qu'on trouve dans les site de bourse (je suis débu
|
Derniers Blogs
IMAGINE CUP 2012, MAKE A SIGN EN FINALEIMAGINE CUP 2012, MAKE A SIGN EN FINALE par junarnoalg
Voilà qui est fait, la nouvelle est officielle ! L'équipe belge "Make a Sign" va au pays des kangourous défendre son projet dans la catégorie Software Design. http://www.imaginecup.com/CompetitionsContent/Competition/WorldwideFinalists.aspx V...
Cliquez pour lire la suite de l'article par junarnoalg KINECT 1.5 IS OUT !KINECT 1.5 IS OUT ! par Vko
La version 1.5 du Kinect For Microsoft vient tout juste de sortir ! Plein de nouveautés: Tracking de squelette en Near Mode Détection en position assise Détection faciale avec un SDK dédié Documentation et des guideline (enfin) Un out...
Cliquez pour lire la suite de l'article par Vko LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) LES ACTUALITéS DE LA SEMAINE SUR C2I.FR (14 MAI - 20 MAI) par richardc
Mise à jour des Web API du 14 Mai
Réservez dès maintenant votre journée du 20 juin pour le Windows Azure Dev Camp 2012 à Paris
Mise à jour de Team Foundation Service
MechCommander 2 sur Windows 8
Entity Framework 5 Release Candidate e...
Cliquez pour lire la suite de l'article par richardc REACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITERREACTIVE EXTENSIONS : CONSOMMER DES SERVICES AVEC RX PARTIE 3, LES PIèGES à éVITER par Groc
Une mauvaise utilisation de rx lors de l'écriture d'une couche d'accès à des services peut conduire à des cas embarassants avec des erreurs mal gérées, des appels qui ne partent lorsqu'ils le devraient, et même des résultats incorrects . le tout nuis...
Cliquez pour lire la suite de l'article par Groc SHAREPOINT BLOG SITE, PROBLèME D'ARCHIVESSHAREPOINT BLOG SITE, PROBLèME D'ARCHIVES par junarnoalg
Dernièrement, nous avons migré le site
myTIC
vers un nouveau serveur SharePoint 2010. Dans les contenus que nous vouloins récupérer, nous avions un certain nombre de blogs.
Nous avons utilisé les commandes Power...
Cliquez pour lire la suite de l'article par junarnoalg
Logiciels
sDEVIS-FACTURES vlPRO (8.1.0.3)SDEVIS-FACTURES VLPRO (8.1.0.3)sDEVIS-FACTURES vlPRO a été mis au point pour les particuliers, créateurs, entrepreneurs, artisa... Cliquez pour télécharger sDEVIS-FACTURES vlPRO 974 Application Server (12.2.4.6)974 APPLICATION SERVER (12.2.4.6)Développez de puissantes applications dans un environnement de 'cloud computing', clusterisé, séc... Cliquez pour télécharger 974 Application Server vPicture (1.4.2.1)VPICTURE (1.4.2.1)Avec vPicture, hébergez vos images facilement et rapidement.
vPicture est un utilitaire simple, ... Cliquez pour télécharger vPicture Easy-Planning (2.2.1.6)EASY-PLANNING (2.2.1.6)Easy-Planning permet de créer des plannings sous la représentation de diagrammes et est adapté au... Cliquez pour télécharger Easy-Planning COM-BACKUP (2.0)COM-BACKUP (2.0)
COM-BACKUP est un logiciel de sauvegarde qui permet de planifier les sauvegardes de vos dossiers ...
Cliquez pour télécharger COM-BACKUP
|