PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Mon Jun 24, 2019 5:29 pm

All times are UTC - 5 hours




Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Sun Oct 09, 2005 7:13 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
Please note that this has now moved to Sourceforge http://sourceforge.net/projects/cssgrapher

Syntax: [ Download ] [ Hide ]
<?php



/*

 A 100% CSS, XHTML 1.1 Compliant Bar Graphing tool

 -- No need to use GD, Renders quickly, Interactive charts,

 -- - Very customizable.

 

 Compatibility: PHP >= 5.0

 

 This class is not licensed, do with it what you will

 (But please give the author credit where due)

 

 Author: d11wtq (Chris Corbyn)

 Date: 2005-10-06

 */




class BarGraph

{

        //Title

        private $ShowTitle = false;                                             //Show the graph title

        private $TitleText = 'New Bar Graph';                   //Graph title

        private $TitleFontColor = '#000000';                    //Graph title color

        private $TitleFontWeight = 'bold';                              //Graph title font weight

        private $TitleFontStyle = 'normal';                             //Graph title font style

        private $TitleTextDecoration = 'underline';             //Graph title text decoration

        private $TitleFontFamily = 'arial,sans-serif';  //Graph title font family

        private $TitleFontSize = '1.0em';                               //Graph title font size

        private $TitleAlign = 'center';                                 //Title left, right or center

        private $ShowTitleBackground = false;                   //Show graph title background

        private $TitleBackgroundColor = '#CCCCFF';              //Graph title background color

       

        //General

        private $XDimension = 0;                                                //Width

        private $YDimension = 0;                                                //Height

       

        private $ShowBorder = false;                                    //Show graph border

        private $LBorderColor = '#CCCCCC';                              //Graph left-border color

        private $RBorderColor = '#CCCCCC';                              //Graph right-border color

        private $TBorderColor = '#CCCCCC';                              //Graph top-border color

        private $BBorderColor = '#CCCCCC';                              //Graph bottom-border color

        private $LBorderStyle = 'solid';                                //Graph left-border style

        private $RBorderStyle = 'solid';                                //Graph right-border style

        private $TBorderStyle = 'solid';                                //Graph top-border style

        private $BBorderStyle = 'solid';                                //Graph bottom-border style

        private $LBorderWidth = '1px';                                  //Graph left-border width

        private $RBorderWidth = '1px';                                  //Graph right-border width

        private $TBorderWidth = '1px';                                  //Graph top-border width

        private $BBorderWidth = '1px';                                  //Graph bottom-border width

        private $ShowBackground = false;                                //Show Graph background

        private $BackgroundColor = '#F4F4F4';                   //Graph background color

        private $BackgroundImage = '';                                  //Graph background Image

        private $BackgroundRepeat = '';                                 //Background repeat (x, y, no-repeat)

        private $BackgroundPosition = '';                               //Background position

       

        private $BarDirection = 'v';                                    //Vertical or horizontal bars

       

        //Bars

        private $ShowBars = true;

        private $BarBackgroundColor = '#DDDDDD';                //Bar background color

        private $BarBorderColor = '#000000';                    //Bar border color

        private $BarBorderWidth = '1px';                                //Bar border width

        private $BarBorderStyle = 'solid';                              //Bar border style

        private $Bars = array();

       

        //Axes

        private $ShowXAxis = true;                                              //Show X-axis

        private $XAxisColor = '#BBBBBB';                                //X-axis color

        private $XAxisWidth = '1px';                                    //X-axis width

        private $XAxisStyle = 'solid';                                  //X-axis style

       

        private $ShowAxisLabels = true;                                 //Show X-axis labels

        private $AxisLabels = array();

        private $AxisLabelFontColor = '#000000';                //X-axis font color

        private $AxisLabelFontWeight = 'normal';                //X-axis font weight

        private $AxisLabelFontStyle = 'normal';         //X-axis font style

        private $AxisLabelTextDecoration = 'none';              //X-axis text decoration

        private $AxisLabelFontFamily = 'arial,sans-serif'; //X-axis font family

        private $AxisLabelFontSize = '0.8em';                   //X-axis font size

       

        private $ShowXAxisLegend = false;                               //Show legend on X-axis

        private $XAxisLegendText = 'X Axis';                    //X-axis legend text

        private $XAxisLegendFontColor = '#000000';              //X-axis legend font color

        private $XAxisLegendFontWeight = 'normal';              //X-axis legend font weight

        private $XAxisLegendFontStyle = 'italic';               //X-axis legend font style

        private $XAxisLegendTextDecoration = 'none';    //X-axis legend text decoration

        private $XAxisLegendFontFamily = 'arial,sans-serif'; //X-axis legend font family

        private $XAxisLegendFontSize = '0.8em';                 //X-axis legend font size

        private $XAxisLegendPosition = 'right';

       

        /* ----------------- */

       

        private $ShowYAxis = true;                                              //Show Y-axis

        private $YAxisColor = '#BBBBBB';                                //See X-axis comment

        private $YAxisWidth = '1px';                                    //See X-axis comment

        private $YAxisStyle = 'solid';                                  //See X-axis comment

       

        private $ShowAxisValues = false;                                //Show Y-axis labels

        private $AxisValuesFontColor = '#000000';               //See X-axis comment

        private $AxisValuesFontWeight = 'normal';               //See X-axis comment

        private $AxisValuesFontStyle = 'normal';                //See X-axis comment

        private $AxisValuesTextDecoration = 'none';             //See X-axis comment

        private $AxisValuesFontFamily = 'arial,sans-serif'; //See X-axis comment

        private $AxisValuesFontSize = '0.8em';                  //See X-axis comment

       

        private $ShowYAxisLegend = false;                               //See X-axis comment

        private $YAxisLegendText = 'Y Axis';                    //See X-axis comment

        private $YAxisLegendFontColor = '#000000';              //See X-axis comment

        private $YAxisLegendFontWeight = 'normal';              //See X-axis comment

        private $YAxisLegendFontStyle = 'italic';               //See X-axis comment

        private $YAxisLegendTextDecoration = 'none';    //See X-axis comment

        private $YAxisLegendFontFamily = 'arial,sans-serif'; //See X-axis comment

        private $YAxisLegendFontSize = '0.8em';                 //See X-axis comment

       

        //Stacks

        private $Vals = array();

        private $BarLengths = array();

       

        //Other graph related propeties

        private $XAxisSize = 0;

        private $YAxisSize = 0;

        private $BarWidth = 'auto';

        private $FFSize;

        private $IESize;

       

        function __construct($w, $h)

        {

                if (is_integer($w)) $this->XDimension = $w;

                else exit('Parameter 1 in object constructor must be an integer: '.gettype($w).' given');

               

                if (is_integer($h)) $this->YDimension = $h;

                else exit('Parameter 2 in object constructor must be an integer: '.gettype($h).' given');

        }

       

        //Overloading to cut down on setters - it does sanity check though

        function __call($method, $args)

        {

                if (isset($this->{$method})

                && gettype($this->{$method}) != 'boolean'

                && gettype ($this->{$method}) != 'array') //We only want to apply to our string/numeric properties

                {

                        if (sizeof($args) == 1) //All of our methods only set one property

                        {

                                $this->CheckError($args[0], __CLASS__.'::'.$method); //Sanity check (is string or number)

                                $this->{$method} = $args[0];

                        }

                        else

                        {

                                exit('Wrong parameter count given for '.__CLASS__.'::'.$method.': Expecting 1: '.count($args).' given');

                        }

                }

                else

                {

                        exit ('Undefined method '.__CLASS__.'::'.$method.' Requested');

                }

        }

       

        private function ThrowError($f, $t) //(Method, value)

        {

                exit('<b>Invlaid argument given</b> in '.$f.'. <b>Parameter must be a string or numeric:</b> '.gettype($t).' given');

        }

       

        private function CheckError($x, $y) //(Value, method)

        {

                if (!is_string($x) && !is_numeric($x)) $this->ThrowError($y, $x);

        }

       

        //Some real setters

        public function ShowTitle($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

               

        public function ShowTitleBackground($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function ShowBorder($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function BorderColor($t)

        {

                $this->CheckError($t, __METHOD__);

                $this->LBorderColor = $t;

                $this->RBorderColor = $t;

                $this->TBorderColor = $t;

                $this->BBorderColor = $t;

        }

       

        public function BorderWidth($t)

        {

                $this->CheckError($t, __METHOD__);

                $this->LBorderWidth = $t;

                $this->RBorderWidth = $t;

                $this->TBorderWidth = $t;

                $this->BBorderWidth = $t;

        }

       

        public function BorderStyle($t)

        {

                $this->CheckError($t, __METHOD__);

                $this->LBorderStyle = $t;

                $this->RBorderStyle = $t;

                $this->TBorderStyle = $t;

                $this->BBorderStyle = $t;

        }

       

        public function ShowBackground($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function ShowBars($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function ShowAxes($x=true)

        {

                $this->ShowXAxis($x);

                $this->ShowYAxis($x);

        }

       

        public function AxisColor($t)

        {

                $this->CheckError($t, __METHOD__);

                $this->XAxisColor = $t;

                $this->YAxisColor = $t;

        }

       

        public function ShowXAxis($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function ShowAxisLabels($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function ShowXAxisLegend($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function ShowYAxis($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function ShowAxisValues($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        public function ShowYAxisLegend($x=true)

        {

                $this->{__FUNCTION__} = $x;

        }

       

        //Graphing methods

       

        /*

         Add some data to the graph

         */


        public function PushValues($x, $assoc=false) //Arrays to insert

        {

                if (is_array($x)) //Sanity check

                {

                        foreach ($x as $k => $val)

                        {

                                if ($assoc) $this->Vals[$k] = $val;

                                else array_push($this->Vals, $val);

                        }

                }

                else exit('Invalid parameter 1 given in '.__METHOD__.'. Expecting array: '.gettype($x).' given');

        }

       

        //Labels for the bar points

        public function PushLabels($x, $assoc=false)

        {

                if (is_array($x))

                {

                        foreach ($x as $k => $val)

                        {

                                if ($assoc) $this->AxisLabels[$k] = $val;

                                else array_push($this->AxisLabels, $val);

                        }

                }

                else exit('Invalid argument given in '.__METHOD__.'. Expecting array: '.gettype($x).' given');

        }

       

        public function PushBarBackgroundColors($x, $a=false)

        {

                if (is_array($x))

                {

                        foreach ($x as $k => $val)

                        {

                                if ($a)

                                {

                                        if (!is_array($this->Bars[$k])) $this->Bars[$k] = array();

                                        $this->Bars[$k]['BackgroundColor'] = $val;

                                }

                                else array_push($this->Bars, array('BackgroundColor' => $val));

                        }

                }

                else exit('Invalid argument given in '.__METHOD__.'. Expecting array: '.gettype($x).' given');

        }

       

        public function PushBarBorderWidths($x, $a=false)

        {

                if (is_array($x))

                {

                        foreach ($x as $k => $val)

                        {

                                if ($a)

                                {

                                        if (!is_array($this->Bars[$k])) $this->Bars[$k] = array();

                                        $this->Bars[$k]['BorderWidth'] = $val;

                                }

                                else array_push($this->Bars, array('BorderWidth' => $val));

                        }

                }

                else exit('Invalid argument given in '.__METHOD__.'. Expecting array: '.gettype($x).' given');

        }

       

        public function PushBarBorderStyles($x, $a=false)

        {

                if (is_array($x))

                {

                        foreach ($x as $k => $val)

                        {

                                if ($a)

                                {

                                        if (!is_array($this->Bars[$k])) $this->Bars[$k] = array();

                                        $this->Bars[$k]['BorderStyle'] = $val;

                                }

                                else array_push($this->Bars, array('BorderStyle' => $val));

                        }

                }

                else exit('Invalid argument given in '.__METHOD__.'. Expecting array: '.gettype($x).' given');

        }

       

        public function PushBarBorderColors($x, $a=false)

        {

                if (is_array($x))

                {

                        foreach ($x as $k => $val)

                        {

                                if ($a)

                                {

                                        if (!is_array($this->Bars[$k])) $this->Bars[$k] = array();

                                        $this->Bars[$k]['BorderColor'] = $val;

                                }

                                else array_push($this->Bars, array('BorderStyle' => $val));

                        }

                }

                else exit('Invalid argument given in '.__METHOD__.'. Expecting array: '.gettype($x).' given');

        }

       

        //Takes a multidimensional associative array "attribute => value"

        // e.g. PushBarAttributes(array('onclick' => 'alert("Foo")'), array('style' => 'opacity: 0.5', 'onmouseover' => 'foo()'), array('id' => 'some_element'))

        // or .. PushBarAttributes(3 => array('onclick' => 'alert("Foo")'), 7 => array('style' => 'opacity: 0.5', 'onmouseover' => 'foo()')) .. for known indices

        public function PushBarAttributes($x, $a=false)

        {

                if (is_array($x))

                {

                        foreach ($x as $k => $arr)

                        {

                                if (!is_array($arr)) exit('Invalid argument given in '.__METHOD__.'. Expecting 2D array: '.gettype($k).' given for element '.$k);

                                if ($a)

                                {

                                        if (!is_array($this->Bars[$k])) $this->Bars[$k] = array();

                                        if (!is_array($this->Bars[$k]['Attributes'])) $this->Bars[$k]['Attributes'] = array();

                                        foreach ($arr as $at => $val)

                                        {

                                                $this->Bars[$k]['Attributes'][$at] = $val;

                                        }

                                }

                                else

                                {

                                        array_push($this->Bars, array('Attributes' => $arr));

                                }

                        }

                }

                else exit('Invalid argument given in '.__METHOD__.'. Expecting array: '.gettype($x).' given');

        }

       

        private function GetBarWidth($d)

        {

                if ($d === 0)

                {

                        //if (empty($this->XAxisLabels)) $this->XAxisLabels = $this->XVals;

                        if (count($this->Vals) > 0)

                        {

                                $count = count($this->Vals);

                                $virtBars = $count + (($count+1)/2); //Imaginary bars

                                $width = floor(($this->XAxisSize*0.98)/$virtBars); //The 0.98 is an IE safeguard for floating divs stying in place

                                return $width;

                        }

                        else return false;

                }

                elseif($d === 1)

                {

                        if (count($this->Vals) > 0)

                        {

                                $count = count($this->Vals);

                                $virtBars = $count + (($count+1)/2); //Imaginary bars

                                $height = floor($this->YAxisSize*0.92/$virtBars);

                                return $height;

                        }

                        else return false;

                }

        }

       

        public function Create($ret=false) //Return or echo the graph

        {

                if (empty($this->Vals)) exit('Cannot render graph without any data. Use '.__CLASS__.'::PushValues to insert data');

               

                if (strtolower($this->BarDirection) == 'v'

                || strtolower($this->BarDirection) == 'vertical'

                || $this->BarDirection === 0)

                {

                        if ($ret) return $this->RenderVertical();

                        else echo $this->RenderVertical();

                }

                elseif (strtolower($this->BarDirection) == 'h'

                || strtolower($this->BarDirection) == 'horizontal'

                || $this->BarDirection === 1)

                {

                        if ($ret) return $this->RenderHorizontal();

                        else echo $this->RenderHorizontal();

                }

                else

                {

                        exit('Cannot render graph. BarDirection must be one of "v", "vertical", 0 or "h", "horizontal", 1');

                }

        }

       

        private function RenderHorizontal()

        {

                $Graph = '<div style="overflow: hidden; text-align: left; width: '.$this->XDimension.'px; height: '.$this->YDimension.'px;';

               

                if ($this->ShowBorder) $Graph .= $this->GraphBorder();

               

                $Graph .= '">'."\n"; //Finish opening outer <div> tag

               

                if ($this->ShowTitle) $Graph .= $this->GraphTitle();

               

                $Graph .= $this->SetAxis();

               

                if ($this->ShowAxisLabels) $Graph .= $this->BuildYAxisLabels();

               

                if ($this->ShowBars

                && (strtolower($this->BarWidth) == 'auto'

                  || (count($this->Vals) + ((count($this->Vals)+1)/2)) * $this->BarWidth * 0.9 > $this->YAxisSize)) $this->BarWidth = $this->GetBarWidth(1);

                if (!$this->BarWidth) $this->ShowBars = false; //Bars either 0 width or no data to show

               

                if ($this->ShowBars) $Graph .= $this->BuildHBars(); //The bars

               

                if ($this->ShowAxisValues)

                {

                        $Graph .= '<div style="font-size: 0; height: 0; clear: both;">&nbsp;</div>'."\n";

                        $Graph .= $this->BuildXAxisValues();

                }

               

                if ($this->ShowXAxisLegend)

                {

                        $Graph .= '<div style="font-size: 0; height: 0; clear: both;">&nbsp;</div>'."\n";

                        $Graph .= $this->SetXLegend(1);

                }

               

                $Graph .= '</div>'."\n"; //Close outer div

               

                return $Graph;

        }

       

        private function RenderVertical()

        {

                $Graph = '<div style="overflow: hidden; text-align: left; width: '.$this->XDimension.'px; height: '.$this->YDimension.'px;';

               

                if ($this->ShowBorder) $Graph .= $this->GraphBorder();

               

                $Graph .= '">'."\n"; //Finish opening outer <div> tag

               

                if ($this->ShowTitle) $Graph .= $this->GraphTitle();

               

                $Graph .= $this->SetAxis();

               

                if ($this->ShowAxisValues) $Graph .= $this->BuildYAxisValues();

               

                //Container for the bars (underneath the axis)

                $Graph .= '<div style="width: '.$this->GetAxisWidth().'px; height: 0; float: right; clear: both;">'."\n";

               

                if ($this->ShowBars

                && (strtolower($this->BarWidth) == 'auto'

                  || (count($this->Vals) + ((count($this->Vals)+1)/2)) * $this->BarWidth * 0.9 > $this->XAxisSize)) $this->BarWidth = $this->GetBarWidth(0);

                if (!$this->BarWidth) $this->ShowBars = false; //Bars either 0 width or no data to show

               

                if ($this->ShowBars) $Graph .= $this->BuildVBars(); //The bars

               

                if ($this->ShowAxisLabels)

                {

                        $Graph .= '<div style="font-size: 0; height: 0; clear: both;">&nbsp;</div>'."\n";

                        $Graph .= $this->BuildXLabels(); //The labels

                }

               

                if ($this->ShowXAxisLegend)

                {

                        $Graph .= '<div style="font-size: 0; height: 0; clear: both;">&nbsp;</div>'."\n";

                        $Graph .= $this->SetXLegend();

                }

               

                $Graph .= '</div>'."\n"; //Close bar holder (underneath X axis - yes it really is!)

                $Graph .= '</div>'."\n"; //Close outer div

               

                return $Graph;

        }

       

        private function BuildYAxisLabels()

        {

                $FFSize = 0;

                $IESize = 0;

                $bars = array();

                foreach ($this->Vals as $k => $v)

                {

                        //Browser specific dimensions - we need to shift by these amounts soon

                        $IESize += ($this->GetBarWidth(1) + floor($this->GetBarWidth(1)/2));

                        $FFSize += ($this->GetBarWidth(1) + floor($this->GetBarWidth(1)/2));

                        $FFSize += ((isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth)*2);

                       

                        $temp = &$bars[];

                       

                        $temp = '<div style="height: '.$this->GetBarWidth(1).'px; border: '.

                        (isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth).' solid transparent'.

                        '; _border: '.

                        (isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth).' solid none'.

                        '; border-left-width: 0; clear: both;">'.(isset($this->AxisLabels[$k]) ? $this->AxisLabels[$k] : '&nbsp;').'</div>'."\n";

                        $temp .= '<div style="font-size: 0; clear: both; height: '.(floor($this->GetBarWidth(1)/2)).'px;">&nbsp;</div>'."\n";

                }

                $bars = array_reverse($bars);

               

                $html = '<div style="text-align: right; width: 6%; overflow: hidden; float: left;'.

                ' font-size: '.$this->AxisValuesFontSize.';'.

                ' color: '.$this->AxisValuesFontColor.';'.

                ' font-weight: '.$this->AxisValuesFontWeight.

                ' font-style: '.$this->AxisValuesFontStyle.

                ' text-decoration: '.$this->AxisValuesTextDecoration.';'.

                ' font-family: '.$this->AxisValuesFontFamily.';'.

                '">'."\n";

               

                $html .= '<div style="font-size: 0; clear: both; height: '.(floor($this->GetAxisHeight() - $FFSize)).'px; _height: '.(floor($this->GetAxisHeight() - $IESize)).'px;">&nbsp;</div>'."\n";

                foreach ($bars as $bar)

                {

                        $html .= $bar;

                }

                $html .= '</div>'."\n";

               

                return $html;

        }

       

        private function BuildXAxisValues()

        {

                $top = max($this->Vals);

                if ($top >= 1 && $v < 10) $t1 = round($top, 1);

                else $t1 = round($top, -1);

               

                $t2 = $t1/2;

                if ($t2 >= 1 && $v < 10) $t2 = round($t2, 1);

                else $t2 = round($t2, -1);

               

                $html = '<div style="width: '.$this->GetAxisWidth().'px; float: right; position: relative; bottom: '.$this->FFSize.'px; _bottom: '.$this->IESize.'px;'.

                ' font-size: '.$this->AxisValuesFontSize.';'.

                ' color: '.$this->AxisValuesFontColor.';'.

                ' font-weight: '.$this->AxisValuesFontWeight.

                ' font-style: '.$this->AxisValuesFontStyle.

                ' text-decoration: '.$this->AxisValuesTextDecoration.';'.

                ' font-family: '.$this->AxisValuesFontFamily.';'.

                ' text-align: right;">'."\n";

                $bw = round($this->XAxisSize * 0.9, 1);

                $html .= '<div style="float: left; width: '.$bw.'px; text-align: right;">'."\n";

                $html .= '<div style="float: left; width: '.(floor($bw/2)).'px; text-align: right;">'.$t2.'</div>'."\n";

                $html .= $t1."\n".'</div>'."\n";

                $html .= '&rarr;&nbsp;</div>'."\n";

                return $html;

        }

       

        private function BuildHBars()

        {

                $top = max($this->Vals);

               

                $this->FFSize = &$FFSize;

                $this->IESize = &$IESize;

               

                $FFSize = 0;

                $IESize = 0;

                $bars = array();

                foreach ($this->Vals as $k => $v)

                {

                        //Browser specific dimensions - we need to shift by these amounts soon

                        $IESize += ($this->GetBarWidth(1) + floor($this->GetBarWidth(1)/2));

                        $FFSize += ($this->GetBarWidth(1) + floor($this->GetBarWidth(1)/2));

                        $FFSize += ((isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth)*2);

                       

                        if (is_numeric($this->Vals[$k]))

                        {

                                $this->BarLengths[$k] = $height = round(($this->Vals[$k]/$top) * 0.9 * $this->XAxisSize, 1); //90% of axis height

                        }

                        else $this->BarLengths[$k] = $height = 0;

                        $temp = &$bars[];

                       

                        $temp = '<div style="font-size: 0; width: '.$this->BarLengths[$k].'px; height: '.$this->GetBarWidth(1).'px; background-color: '.

                        (isset($this->Bars[$k]['BackgroundColor']) ? $this->Bars[$k]['BackgroundColor'] : $this->BarBackgroundColor).

                        '; border: '.

                        (isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth).' '.

                        (isset($this->Bars[$k]['BorderStyle']) ? $this->Bars[$k]['BorderStyle'] : $this->BarBorderStyle).' '.

                        (isset($this->Bars[$k]['BorderColor']) ? $this->Bars[$k]['BorderColor'] : $this->BarBorderColor).'; border-left-width: 0; float: left;'; //Think of a cleaner way than leaving the quote open for a while? **

                       

                        if (isset($this->Bars[$k]['Attributes'])) $temp .= $this->SetBarAttributes($k);

                        else $temp .= '"';

                       

                        $temp .= '>&nbsp;</div>'."\n";

                        $temp .= '<div style="font-size: 0; clear: both; height: '.(floor($this->GetBarWidth(1)/2)).'px;">&nbsp;</div>'."\n";

                }

                $bars = array_reverse($bars);

               

                $html = '<div style="height: '.$FFSize.'px; _height: '.$IESize.'px; width: '.$this->GetAxisWidth().'px; position: relative; float: right; bottom: '.$FFSize.'px; _bottom: '.$IESize.'px; _left: '.$this->YAxisWidth.';">'."\n";

                foreach ($bars as $bar)

                {

                        $html .= $bar;

                }

                $html .= '</div>'."\n";

               

                return $html;

        }

       

        private function BuildYAxisValues()

        {

                $top = max($this->Vals);

                if ($top >= 1 && $v < 10) $t1 = round($top, 1);

                else $t1 = round($top, -1);

               

                $t2 = $t1/2;

                if ($t2 >= 1 && $v < 10) $t2 = round($t2, 1);

                else $t2 = round($t2, -1);

               

                $bw = (int) $this->BarBorderWidth;

               

                $html = '<div style="text-align: right; z-index: 2; overflow: visible; float: right; position: relative; right: '.($bw*2).'px; height: '.$this->GetAxisHeight().'px;'.

                ' font-size: '.$this->AxisValuesFontSize.';'.

                ' color: '.$this->AxisValuesFontColor.';'.

                ' font-weight: '.$this->AxisValuesFontWeight.

                ' font-style: '.$this->AxisValuesFontStyle.

                ' text-decoration: '.$this->AxisValuesTextDecoration.';'.

                ' font-family: '.$this->AxisValuesFontFamily.';'.

                '">'."\n";

               

                $bh = $this->GetAxisHeight() - round(0.9 * $this->YAxisSize, 1);

                $html .= '<div style="height: '.$bh.'px; clear: both;">&nbsp;</div>'."\n";

                $html .= '<div style="height: '.(floor(($this->GetAxisHeight()-$bh)/2)).'px;">&uarr;&nbsp;'.$t1.'</div>'."\n";

                $html .= '<div style="clear: both;">'.$t2.'</div>'."\n";

                $html .= '</div>'."\n";

                return $html;

        }

       

        private function SetXLegend($hor=false)

        {

                if (!$hor) $bot = ' bottom: '.max($this->BarLengths).'px;';

                else $bot = ' bottom: '.$this->FFSize.'px; _bottom: '.$this->IESize.'px;';

               

                $html = '<div style="width: '.$this->XAxisSize.'px;'.

                                ' font-weight: '.$this->XAxisLegendFontWeight.';'.

                                ' font-size: '.$this->XAxisLegendFontSize.';'.

                                ' color: '.$this->XAxisLegendFontColor.';'.

                                ' font-family: '.$this->XAxisLegendFontFamily.';'.

                                ' font-style: '.$this->XAxisLegendFontStyle.';'.

                                ' position: relative;'.

                                $bot.

                                ' text-align: '.$this->XAxisLegendPosition.';'.

                                ' float: right;">'.

                                '&nbsp;'.$this->XAxisLegendText.'&nbsp;'.

                                '</div>'."\n";

                return $html;

        }

       

        private function BuildXLabels()

        {

                $d = max($this->BarLengths);

                $html = '';

                foreach ($this->Vals as $k => $v)

                {

                        $text = (isset($this->AxisLabels[$k]) ? $this->AxisLabels[$k] : '&nbsp;');

                        $html .= '<div style="font-size; 0; width: '.(floor($this->GetBarWidth(0)/2)).'px; float: left;">&nbsp;</div>';

                        $html .= '<div style="font-size: '.$this->AxisLabelFontSize.

                                        '; font-family: '.$this->AxisLabelFontFamily.

                                        '; color: '.$this->AxisLabelFontColor.

                                        '; font-weight: '.$this->AxisLabelFontWeight.

                                        '; font-style: '.$this->AxisLabelFontStyle.

                                        '; text-decoration; '.$this->AxisLabelTextDecoration.

                                        '; width: '.$this->BarWidth.'px'.

                                        '; text-align: center; float: left; overflow: visible; position: relative; bottom: '.$d.'px; border: '.(isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth).' solid transparent; _border: '.(isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth).' solid none;">';

                        $html .= $text;

                        $html .= '</div>'."\n";

                }

                return $html;

        }

       

        private function BuildVBars()

        {

                $html = '';

                $top = max($this->Vals);

               

                //Get the bar heights

                foreach ($this->Vals as $k => $v)

                {

                        if (is_numeric($this->Vals[$k]))

                        {

                                $this->BarLengths[$k] = $height = round(($this->Vals[$k]/$top) * 0.9 * $this->YAxisSize, 1); //90% of axis height

                        }

                        else $this->BarLengths[$k] = $height = 0;

                        $html .= '<div style="font-size; 0; width: '.(floor($this->BarWidth/2)).'px; float: left;">&nbsp;</div>'."\n";

                        $html .= '<div style="font-size: 0; width: '.$this->BarWidth.'px; height: '.$height.'px; background-color: '.

                        (isset($this->Bars[$k]['BackgroundColor']) ? $this->Bars[$k]['BackgroundColor'] : $this->BarBackgroundColor).

                        '; border: '.

                        (isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth).' '.

                        (isset($this->Bars[$k]['BorderStyle']) ? $this->Bars[$k]['BorderStyle'] : $this->BarBorderStyle).' '.

                        (isset($this->Bars[$k]['BorderColor']) ? $this->Bars[$k]['BorderColor'] : $this->BarBorderColor).'; border-bottom-width: 0; float: left; position: relative; bottom: '.($height+(isset($this->Bars[$k]['BorderWidth']) ? $this->Bars[$k]['BorderWidth'] : $this->BarBorderWidth)+$this->XAxisWidth).'px; _bottom: '.($height+$this->XAxisWidth).'px;'; //Think of a cleaner way than leaving the quote open for a while? **

                       

                        if (isset($this->Bars[$k]['Attributes'])) $html .= $this->SetBarAttributes($k);

                        else $html .= '"';

                       

                        $html .= '>&nbsp;</div>'."\n";

                }

                return $html;

        }

       

        private function SetBarAttributes($n)

        {

                $html = '';

                $st = false;

                foreach ($this->Bars[$n]['Attributes'] as $at => $val)

                {

                        if (strtolower($at) == 'style' && !$st) //** quote was left open

                        {

                                $html = ' '.$val.';"'.$html;

                                $st = true;

                        }

                        else $html .= ' '.$at.'="'.$val.'"';

                }

                return ($st ? '' : '"').$html; //Prepend the closing style quote

        }

       

        private function SetAxis()

        {

                $html = '<div style="font-size: 0; width: '.$this->GetAxisWidth().'px;'.

                                ' height: '.$this->GetAxisHeight().'px;';

                if ($this->ShowBackground) $html .= $this->GraphBackground();

                if ($this->ShowXAxis) $html .= " border-bottom: {$this->XAxisWidth} {$this->XAxisStyle} {$this->XAxisColor};";

                if ($this->ShowYAxis) $html .= " border-left: {$this->YAxisWidth} {$this->YAxisStyle} {$this->YAxisColor};";

                $html .= ' float: right;">&nbsp;</div>';

               

                return $html;

        }

       

        private function GetAxisHeight()

        {

                if ($this->YAxisSize === 0)

                {

                        //This was all trial and error - there's no science here

                        $h = $this->YDimension * 0.97 - 16;

                        if ($this->ShowTitle) $h = $h * 0.97 - 16;

                        if ($this->ShowXAxisLegend) $h = $h * 0.97 - 16;

                        return $this->YAxisSize = $h;

                }

                else

                {

                        return $this->YAxisSize;

                }

        }

       

        private function GetAxisWidth()

        {

                if ($this->XAxisSize === 0)

                {

                        return $this->XAxisSize = $this->XDimension * 0.93;

                }

                else

                {

                        return $this->XAxisSize;

                }

        }

       

        private function GraphBorder()

        {

                $css = " border-left: {$this->LBorderWidth} {$this->LBorderStyle} {$this->LBorderColor};".

                                " border-right: {$this->RBorderWidth} {$this->RBorderStyle} {$this->RBorderColor};".

                                " border-top: {$this->TBorderWidth} {$this->TBorderStyle} {$this->TBorderColor};".

                                " border-bottom: {$this->BBorderWidth} {$this->BBorderStyle} {$this->BBorderColor};";

                return $css;

        }

       

        private function GraphBackground()

        {

                $css = " background-color: {$this->BackgroundColor};";

                if ($this->BackgroundImage != '') $css .= " background-image: url({$this->BackgroundImage});";

                if ($this->BackgroundRepeat != '') $css .= " background-repeat: {$this->BackgroundRepeat};";

                if ($this->BackgroundPosition != '') $css .= " background-position: {$this->BackgroundPosition};";

                return $css;

        }

       

        private function GraphTitle()

        {

                $html = '<div style="color: '.$this->TitleFontColor.

                                '; font-size: '.$this->TitleFontSize.

                                '; font-weight: '.$this->TitleFontWeight.

                                '; font-style: '.$this->TitleFontStyle.

                                '; font-family: '.$this->TitleFontFamily.

                                '; text-decoration: '.$this->TitleTextDecoration.

                                '; text-align: '.$this->TitleAlign.';';

                if ($this->ShowTitleBackground) $html .= ' background-color: '.$this->TitleBackgroundColor.';';

               

                $html .= ' padding: 1px; overflow: hidden; white-space: nowrap;">'."\n"; //Finish opening title <div>

               

                $html .= $this->TitleText."\n";

               

                $html .= '</div>'."\n";

               

                return $html;

        }



}



?>


Last edited by Chris Corbyn on Mon Mar 20, 2006 2:24 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 09, 2005 8:17 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
It's actually very nice and works in both IE and Firefox. The whole things runs in under 1000th of a second on my home computer with 10 values set.

Features:
    * Creates fixed dimension bar graphs without GD
    * Highly customizable (fonts, titles, axes, legends...)
    * Renders quickly
    * Lower bandwidth than JP Graph
    * Ability to manipulate each individual bar
    * Horizontal or vertical rendering
    * JavaScript/DHTML integration capable

Limitations (in this first version):
    * Unable to handle negative values (Will be added very soon)


Usage:

It's actually very simple to use despite it's ugly length.

The basics:
Syntax: [ Download ] [ Hide ]
$Graph = new BarGraph(600, 200); //Instantiate with the (width, height) of graph in pixels



$data = array(

    10,

    12,

    64,

    78,

    5,

    89.4

);



$Graph->PushValues($data); //Insert some data - run this as many times as needed (like array_push())

$Graph->Create(); //Output the graph (very basic)



//or......

$output = $Graph->Create(true);

//Setting the first paramater to true returns the grpah as opposed to echoing it


See example 1 here: http://w3style.co.uk/BarGraph/example1.php

We might want to have a title and some labels on our axes....

Syntax: [ Download ] [ Hide ]
$Graph = new BarGraph(400, 130);



$data = array(

    10,

    12,

    64,

    78,

    5,

    89.4

);



$labels = array(

    'Foo',

    'Bar',

    'Bob',

    'Joe',

    'Jim',

    '???'

);



$Graph->PushValues($data);



$Graph->PushLabels($labels); //Insert some labels like we did for the values

$Graph->ShowAxisLabels(); //Tell the class to display them



$Graph->TitleText('Example 2: Adding Labels/Titles'); //Give it a title

$Graph->ShowTitle(); //Display it



$Graph->Create();


See it here: http://w3style.co.uk/BarGraph/example2.php

OK, you get the idea... you can manipulate the appearance quite a lot - one last example. I'll list all the methods and what they do after this.

Syntax: [ Download ] [ Hide ]
$Graph = new BarGraph(550, 300);



$data = array(

    10,

    12,

    'foo' => 64,  //We can manipulate individual bars associately**

    78,

    5,

    89.4

);



$labels = array(

    'Foo',

    'Bar',

    'foo' => 'Bob',

    'Joe',

    'Jim',

    '???'

);



$Graph->PushValues($data, 1);



$Graph->PushLabels($labels, 1); //Insert some labels like we did for the values

$Graph->ShowAxisLabels(); //Tell the class to display them



$Graph->ShowAxisValues(); //Ticks on axis



$Graph->XAxisLegendText('Example X Axis Legend');

$Graph->ShowXAxisLegend();



$Graph->TitleText('Example 2: Adding Labels/Titles'); //Give it a title

$Graph->TitleFontColor('#555599');

$Graph->TitleFontSize('0.8em');

$Graph->ShowTitle(); //Display it



//Some styling (background)

$Graph->BackgroundColor('#FFFFFF');

$Graph->BackgroundImage('gradient.png');

$Graph->BackgroundRepeat('repeat-x');

$Graph->BackgroundPosition('top-left');

$Graph->ShowBackground();



//Brighten up the bars

$Graph->BarBackgroundColor('#6BE849');



//Fiddle with the bar we called foo

//The idea behind this method is that you can set many at once (hence the array)

$Graph->PushBarBackgroundColors(array('foo' => '#FFCCCC'), 1); //The second parameter means we refer to the bar associately

//Make foo clickable

$Graph->PushBarAttributes(array('foo' => array('onclick' => "alert('You clicked foo')")), 1);



$Graph->Create();


View it here: http://w3style.co.uk/BarGraph/example3.php

Available methods:
>>PushValues(array array [, bool assoc switch])
Pushes new values into the graph. Values appear in the order they were added. Optionally, if the second paramater is set true the array keys are used associatively. This helps when trying to manipulate a specific bar.

>>PushLabels(array array [, bool assoc switch])
Pushes new labels into the graph. Labels appear in the order they were added. Optionally, if the second paramater is set true the array keys are used associatively.

>>ShowTitle([bool switch])
Displays or hides the graph title

>>TitleText(string text)
Sets the text for the title

>>TitleFontColor(), TitleFontWeight(), TitleFontStyle(), TitleFontColor(), TitleTextDecoration(), TitleBackgroundColor(), TitleFontFamily()
Change the appearance of the title. All take a single string as a parameter. Standard CSS values are accepeted.

>>TitleAlign(string alignment)
One of center, left, or right

>>ShowAxis([bool switch])
Show or hide both axes

>>ShowXAxis([bool switch]), ShowYAxis([bool switch])
Show or hide the individual axis

>>AxisColor(string color)
Set the axis color using html/css accpeted codes

>>XAxisColor(string color), YAxisColor(string color)
See above

>>AxisStyle(string style), XAxisStyle(), YAxisStyle()
Dotted, dashed, solid or double (CSS modes)

>>AxisWidth(string size)
Set both axis widths. You need to use CSS units as a string (e.g. '2px' as opposed to 2)

>>XAxisWidth(), YAxisWidth()
See above

>>ShowBars([bool switch])
Show or hide the bars

>>BarBorderWidth(string size)
You must get the idea by now :P

>>BarBorderColor(string color)

>>BarBorderStyle(string style)
Dotted, solid, dashed, double (CSS standards)

>>BackgroungColor(string color)
Background for the graph

>>BackgroundImage(), BackgroundRepeat(), BackgroundPosition()
Background Image for the graph

>>ShowXAxisLegend([bool switch])

>>ShowAxisValues([bool switch])

>>ShowAxisLabels([bool switch])

>>AxisLabelFontColor(), AxisLabelFontStyle(), AxisLabelFontWeight(), AxisLabelFontFamily(), AxisLabelTextDecoration()

>>BarDirection(string/Int mode)
Changes the orientation of the bars. Set this to 'h', or 'v'.

>>BarWidth(string size)
Set this to "auto" to have the class determine the best widths for the bars. This is the default. You can also set fixed width using CSS units here (e.g. '20px')


Last edited by Chris Corbyn on Sun Oct 09, 2005 8:31 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 09, 2005 8:27 pm 
Offline
DevNet Resident
User avatar

Joined: Wed Sep 25, 2002 7:47 pm
Posts: 1708
very nice. i've seen this same type of method used with tables instead though. It's a great way to get away from GD, however, GD would still bring better performance ends. The overhead you will experience with larger loads will be a little bit higher, but not by much, and that is simply due to class versus modules is 9 x out of 10 gonna be slower.

otherwise, nice class and good work.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 09, 2005 8:39 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
infolock wrote:
....however, GD would still bring better performance ends. The overhead you will experience with larger loads will be a little bit higher, but not by much, and that is simply due to class versus modules is 9 x out of 10 gonna be slower....


True about the modules versus classes. But GD alone will not make graph's. There are classes out there (JPGraph) to do this, so you still end up with the object overhead in that sense :)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 12:03 am 
Offline
Tutorials Group

Joined: Sun Jan 04, 2004 11:30 pm
Posts: 2692
infolock wrote:
very nice. i've seen this same type of method used with tables instead though. It's a great way to get away from GD, however, GD would still bring better performance ends. The overhead you will experience with larger loads will be a little bit higher, but not by much, and that is simply due to class versus modules is 9 x out of 10 gonna be slower.

otherwise, nice class and good work.

I've actually had fairly strong impact from the jpgraph and gd chart generation.. I'm curious to test this against the same from them, as I think d11wtq's is actually faster.

Regardless, I love the css, and its sharp. The library does seem a bit large, but it does what its supposed to, fast, and very flexibly.

Nice work d11wtq.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 8:00 am 
Offline
DevNet Resident
User avatar

Joined: Wed Sep 25, 2002 7:47 pm
Posts: 1708
aye, that's pretty much the same thing i was thinking. was the speed difference will be, and how this class will handle large data and amounts. let me know your finds Roja as i'm kinda curious to know myself. just don't have the time to do the testing here :?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 8:36 am 
Offline
DevNet Resident
User avatar

Joined: Mon Aug 22, 2005 12:11 pm
Posts: 1912
Location: Leeds/Manchester, England
that is a very nice class indeed. good job mate.

if i ever need to make graphs on a website i will definately search for this thread! :wink:


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 11:08 am 
Offline
DevNet Resident

Joined: Fri Sep 16, 2005 9:06 pm
Posts: 1375
beautifully done.beautiful


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 12:01 pm 
Offline
Site Admin
User avatar

Joined: Tue Dec 23, 2003 3:10 am
Posts: 11470
Location: Toronto
Great looking class ;)
Will be using this


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 1:55 pm 
Offline
Briney Mod
User avatar

Joined: Mon Jan 19, 2004 7:11 pm
Posts: 6446
Location: 53.01N x 112.48W
Wow! Very impressive. I'll definitely be using this.

By the way, is there any reason this can't be easily modified to work with PHP4? I'm seeing some PHP5 constructs that can definitely be mimiced with PHP4, but I haven't look too closely.

_________________
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 5:21 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
pickle wrote:
Wow! Very impressive. I'll definitely be using this.

By the way, is there any reason this can't be easily modified to work with PHP4? I'm seeing some PHP5 constructs that can definitely be mimiced with PHP4, but I haven't look too closely.


If you want to convert it to PHP4 then:

a) Change the constructor
b) Drop all the "private" and "public" declarations
c) Replace "__METHOD__" special constants with something that works ( __FUNCTION__ )
d) Don't use overloading ( __call() ) for most of the setters - phyiscally code every single setter method (ouch!)

I don't really have any plans to convert it since it was primarily written for use on a project at work (in my own time) where we use PHP5 OOP heavily. It can be done though.

I may update the code in a day or two since I have modified some of the code to behave in a nicer way and corrected a couple of *minor* bugs.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 5:23 pm 
Offline
Briney Mod
User avatar

Joined: Mon Jan 19, 2004 7:11 pm
Posts: 6446
Location: 53.01N x 112.48W
d11wtq wrote:
I may update the code in a day or two since I have modified some of the code to behave in a nicer way and corrected a couple of *minor* bugs.


Well, once you do, let me know. I'll probably convert it to PHP4 since we use that heavily here at my work ;)

_________________
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 4:28 pm 
Offline
Forum Commoner

Joined: Thu Feb 12, 2004 3:28 am
Posts: 35
Location: Copenhagen, Denmark
Has this code been converted to php4?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 4:33 pm 
Offline
Briney Mod
User avatar

Joined: Mon Jan 19, 2004 7:11 pm
Posts: 6446
Location: 53.01N x 112.48W
Heck no. To be honest, I forgot I made that claim. If ~d11wtq's updated the code, then I guess I'll start on it.

_________________
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 8:18 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
StumpDK wrote:
Has this code been converted to php4?


This is on sourceforge. I put it there so that when I get chance I can work on some of the bugs (there are a handful), optionally allow the data to be returned as an array with the CSS in one index and the XHTML in the other, and also refactor it to allow the possiblity of other graph types (like JP Graph)... I know it can be done because I've seen JS methods for it.

http://sourceforge.net/projects/cssgrapher

If anyone does offer updates/bug fixes/compatibility fixes I'd quite like to know so I can update it :) If anyone fancies digging into what's on SF PM me because I prob won't be working on it for the next 2 months personally at least :(


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 47 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group