Location: PHPKode > scripts > Circle Chart using SVG > circle-chart-using-svg/circlechart.php
<?

/**
* Width of the page used, in this case A4 size in centimetres
*/
define ("SIZEWIDTHCM",21);
/**
* Height of the page used, in this case A4 size in centimetres
*/
define ("SIZEHEIGHTCM",27);
/**
* Left Margin 
*/ 
define ("BEGINXSVG",10);
/**
* Top Margin 
*/ 
define ("BEGINYSVG",30);
/**
* Characters to be displayed in a line
*/ 
define ("MAXCHARACTERS",30);

/**
* This class is used to represent the information using the svg format
*/

class CDataChart
{
	var $m_arrAttributes = array();
	var $m_arrObjects = array();
	
	function GetMinAttribute($strAttribute)
	{
		if (count($this->m_arrObjects) == 0)
			return 0;
		$valueMin =$this->m_arrObjects[0]->$strAttribute;
		reset($this->m_arrObjects);
		while (list($key, $object) = each($this->m_arrObjects))
		{
			$valueAct =$object->$strAttribute;
			if ($valueAct < $valueMin)
			{
				$valueMin=$valueAct;
			}
		}
		return $valueMin;
	}
	
	function GetMaxAttribute($strAttribute)
	{
		if (count($this->m_arrObjects) == 0)
			return 0;
		$valueMax =$this->m_arrObjects[0]->$strAttribute;
		reset($this->m_arrObjects);
		while (list($key, $object) = each($this->m_arrObjects))
		{
			$valueAct =$object->$strAttribute;
			if ($valueAct > $valueMax)
			{
				$valueMax=$valueAct;
			}
		}
		return $valueMax;
	}
	
	function GetNumAttributes()
	{
		return $this->m_arrAttributes;
	}
}

class CCircleChart
{
	/**
	* Data
	*/
	var $m_dataChart;
	/**
	* Width of the page
	*/
	var $m_nWidthSVG =SIZEWIDTHCM;
	/**
	* Height of the page
	*/
	var $m_nHeightSVG =SIZEHEIGHTCM;	
	/**
	* Coord Center X of the data circle
	*/
	var $m_nCenterX;		
	/**
	* Coord Center Y of the data circle
	*/
	var $m_nCenterY;		
	/**
	* Radius of the data circle
	*/
	var $m_nRadius;		
	/**
	* Coord Center X of the attributes circle
	*/
	var $m_nCenterXAttributes;		
	/**
	* Coord Center Y of the attributes circle
	*/
	var $m_nCenterYAttributes;		
	/**
	* Radius of the attributes circle
	*/
	var $m_nRadiusAttributes;		
	
	/**
	* Constructor of the class
	*/
	function CCircleChart($strPath)
	{
		$this->m_dataChart = new CDataChart();
		$this->m_strPath =$strPath;
		$strPathTemp =sprintf("%s",$this->m_strPath);
		$this->m_fileSVG = @fopen($strPathTemp,"w");
	}
	
	/**
	* Write to the file the standard svg headers, if you want use another measure units
	* you have to change them here
	*/
	function HeaderSVG()
	{
		$strHeaderSVG ="<?xml version=\"1.0\" standalone=\"no\"?>";
		$strHeaderSVG .="<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" ";
		$strHeaderSVG .="\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">";
		
		$strTemp =sprintf("<svg width=\"%dcm\" height=\"%dcm\" viewBox=\"0 0 %d %d\" ",
					$this->m_nWidthSVG,$this->m_nHeightSVG,
					$this->m_nWidthSVG*100,$this->m_nHeightSVG*100);
		$strHeaderSVG .=$strTemp;
		$strHeaderSVG .="xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\">\n";
		
		fwrite($this->m_fileSVG,$strHeaderSVG);
	}
	
				
	/**
	* Close the actual svg file, and write the last of svg end
	*/
	function CloseSVG()
	{
		fwrite($this->m_fileSVG,"</svg>");
		fclose($this->m_fileSVG);
	}
	
	/**
	* Adjust the "normal" coordX to the SVG axis
	*/
	function ConvertXtoXSVG($nX)
	{
		return $nX;
	}
	/**
	* Adjust the "normal" coordY to the SVG axis
	*/
	function ConvertYtoYSVG($nY)
	{
		return $this->m_nHeightSVG*100 - $nY;
	}
	
	/**
	* Draw a circle using the parameters
	*/
	function DrawCircle($nCenterX,$nCenterY,$nRadius,$strFill,$strStroke,$nStrokeWidth,$strDashArray,$strEvents = "")
	{
		$nCenterXSVG =$this->ConvertXtoXSVG($nCenterX);
		$nCenterYSVG =$this->ConvertYtoYSVG($nCenterY);
		fwrite($this->m_fileSVG,"<circle cx=\"$nCenterXSVG\" cy=\"$nCenterYSVG\" r=\"$nRadius\" ");
			fwrite($this->m_fileSVG," style=\"fill$strFill;stroke$strStroke;stroke-width:$nStrokeWidth;stroke-dasharray:$strDashArray\"");
		fwrite($this->m_fileSVG," $strEvents/>\n");
	}
	
	/**
	* Calculate the coords corresponding to an angle of a circle
	*/
	function CalcAngle($nCenterX,$nCenterY,$nRadius,$nAngle,&$nPosX,&$nPosY)
	{
		$nAngleRad =$nAngle * 2 * pi() / 360;
		$nPosX =(int)(cos($nAngleRad)*$nRadius + $nCenterX);
		$nPosY =(int)(sin($nAngleRad)*$nRadius + $nCenterY);
	}

	/**
	* Draw a line from the center to an angle of the circle
	*/
	function LineCircle($nCenterX,$nCenterY,$nRadius,$nAngle,$strFill,$strStroke,$nStrokeWidth,$strDashArray)
	{
		$nAngleRad =$nAngle * 2 * pi() / 360;
		$nPosX =(int)(cos($nAngleRad)*$nRadius + $nCenterX);
		$nPosY =(int)(sin($nAngleRad)*$nRadius + $nCenterY);
		
		$nPosXSVG =$this->ConvertXtoXSVG($nPosX);
		$nPosYSVG =$this->ConvertYtoYSVG($nPosY);
		$nCenterXSVG =$this->ConvertXtoXSVG($nCenterX);
		$nCenterYSVG =$this->ConvertYtoYSVG($nCenterY);
		fwrite($this->m_fileSVG,"<line x1=\"$nCenterXSVG\" y1=\"$nCenterYSVG\" x2=\"$nPosXSVG\" y2=\"$nPosYSVG\" ");
		fwrite($this->m_fileSVG,"fill=\"$strFill\" stroke=\"$strStroke\" stroke-width=\"$nStrokeWidth\" stroke-dasharray=\"$strDashArray\" />\n");			
	}


	/**
	* Draw a text using the parameters
	*/
	function Text($strText,$nPosX,$nPosY,$strFont,$nFontSize,$strFill,$strAnchor)
	{
		$nPosXSVG =$this->ConvertXtoXSVG($nPosX);
		$nPosYSVG =$this->ConvertYtoYSVG($nPosY);
		fwrite($this->m_fileSVG,"<text x=\"$nPosXSVG\" y=\"$nPosYSVG\" font-family=\"$strFont\" font-size=\"$nFontSize\" ");
		fwrite($this->m_fileSVG,"fill=\"$strFill\" text-anchor=\"$strAnchor\">$strText</text>\n");
	}
	
	/**
	* Draw a text with id using the parameters to change it dinamically
	*/
	function TextId($strId,$strText,$nPosX,$nPosY,$strFont,$nFontSize,$strFill,$strAnchor)
	{
		$nPosXSVG =$this->ConvertXtoXSVG($nPosX);
		$nPosYSVG =$this->ConvertYtoYSVG($nPosY);
		fwrite($this->m_fileSVG,"<text id=\"$strId\" x=\"$nPosXSVG\" y=\"$nPosYSVG\" font-family=\"$strFont\" font-size=\"$nFontSize\" ");
		fwrite($this->m_fileSVG,"fill=\"$strFill\" text-anchor=\"$strAnchor\">$strText</text>\n");
	}
	
	/**
	* Calculate the lenght of an arc
	*/
	function GetArcLength($nCenterX,$nCenterY,$nRadius,$nAngle)
	{
		$this->CalcAngle($nCenterX,$nCenterY,$nRadius,$nAngle,$nPosX,$nPosY);
		$this->CalcAngle($nCenterX,$nCenterY,$nRadius,2*$nAngle,$nPosX2,$nPosY2);
		
		return sqrt(pow(abs($nPosX - $nPosX2),2) + pow(abs($nPosY - $nPosY2),2)) / 2;
	}

	/**
	* Draw the lines from the data positions to center
	*/
	function LinesToCenter()
	{
		$nVarAngle =360 / count($this->m_dataChart->m_arrObjects);
		$nAngle =90;
		for ($j=0;$j<count($this->m_dataChart->m_arrObjects);$j++)
		{
			$this->LineCircle($this->m_nCenterX,$this->m_nCenterY,$this->m_nRadius,$nAngle,"blue","red",5,"10 5");
			$nAngle =$nAngle + $nVarAngle;
		} 
	}

	/**
	* Draw the text of the attributes circle
	*/
	function TextData()
	{
		$nVarAngle =360 / count($this->m_dataChart->m_arrObjects);
		$nAngle =90;
		$nArcLength =20 + $this->m_nRadius + $this->GetArcLength($this->m_nCenterX,$this->m_nCenterY,$this->m_nRadius,$nVarAngle);
		for ($j=0;$j<count($this->m_dataChart->m_arrObjects);$j++)
		{
			$strIndexAct =$this->m_dataChart->m_arrObjects[$j]->m_strIndex;
			$this->CalcAngle($this->m_nCenterXAttributes,$this->m_nCenterYAttributes,
					  $this->m_nRadiusAttributes+20,$nAngle,$nPosX,$nPosY);
			$this->Text($strIndexAct,$nPosX,$nPosY,"Verdana",20,"black","middle");
			$this->CalcAngle($this->m_nCenterX,$this->m_nCenterY-15,
					 $nArcLength,$nAngle,$nPosX,$nPosY);
			$this->Text($strIndexAct,$nPosX,$nPosY,"Verdana",20,"black","middle");
			$nAngle =$nAngle + $nVarAngle;
		}
		$this->TextId("index","INDEX",$this->m_nCenterXAttributes,$this->m_nCenterYAttributes-30,"Verdana",30,"black","middle");	
	}
	
	/**
	* Draw the data in the data circle
	*/
	function DrawData()
	{
		$nRadius =$this->m_nRadius;
		$nRadiusAttributes =$this->m_nRadiusAttributes;
		
		$nVarAngle =360 / count($this->m_dataChart->m_arrObjects);
		$nVarRadius =$nRadius / count($this->m_dataChart->m_arrAttributes);
		$nVarRadiusAttributes =$nRadiusAttributes / count($this->m_dataChart->m_arrAttributes);
		for($i=0;$i<count($this->m_dataChart->m_arrAttributes);$i++)
		{
			$nAngle =90;
			$strAttribute =$this->m_dataChart->m_arrAttributes[$i];
			$valueMin =$this->m_dataChart->GetMinAttribute($strAttribute);
			$valueMax =$this->m_dataChart->GetMaxAttribute($strAttribute);
			$valueMed =$valueMin + ($valueMax - $valueMin)/2;
			$nArcLength =$this->GetArcLength($this->m_nCenterX,$this->m_nCenterY,$nRadius,$nVarAngle);

			$maxArea =pi() * pow($nArcLength,2);
			
			$this->Text($strAttribute,$this->m_nCenterXAttributes,$this->m_nCenterYAttributes + $nRadiusAttributes -30,"Verdana",20,"black","middle");
			$this->TextId($strAttribute,"DATA",$this->m_nCenterXAttributes,$this->m_nCenterYAttributes + $nRadiusAttributes-60,"Verdana",25,"black","middle");	
			for ($j=0;$j<count($this->m_dataChart->m_arrObjects);$j++)
			{
				$valueAct =$this->m_dataChart->m_arrObjects[$j]->$strAttribute;
				$nRadiusAct =sqrt(($maxArea*$valueAct)/(pi()*$valueMax));
				$this->CalcAngle($this->m_nCenterX,$this->m_nCenterY,$nRadius,$nAngle,$nPosX,$nPosY);
				
				if ($valueAct < $valueMed)
				{
					$nColor =255 * (1-($valueAct - $valueMin)/($valueMax - $valueMin));
					$strColor =":rgb(0,$nColor,0)";
				}
				else
				{	
					$nColor =255 * (1-($valueAct - $valueMin)/($valueMax - $valueMin));
					$strColor =":rgb(0,$nColor,0)";
				}
		
				$strEvents=" onmouseover=\"change" .$this->m_dataChart->m_arrObjects[$j]->m_strIndex ."(evt)\"";
		
				$this->DrawCircle($nPosX,$nPosY,$nRadiusAct,$strColor,":rgb(0,255,0)",3,"5 5",$strEvents);
				$nAngle =$nAngle + $nVarAngle;
			}
			$nRadius =$nRadius - $nVarRadius;
			$nRadiusAttributes =$nRadiusAttributes - $nVarRadiusAttributes;
		}
	}
	
	/**
	* Generate the scripts to link the data circle and the attributes circle
	* Be careful with the names
	*/
	function GenScripts()
	{
		fwrite($this->m_fileSVG,"<script type=\"text/ecmascript\"><![CDATA[\n");
		
		for ($i=0;$i<count($this->m_dataChart->m_arrObjects);$i++)
		{
			$strIndex =$this->m_dataChart->m_arrObjects[$i]->m_strIndex;
			fwrite($this->m_fileSVG,"function change" . $strIndex ."(evt){\n");
			fwrite($this->m_fileSVG,"var svgdoc=evt.target.getOwnerDocument();\n");
			for ($j=0;$j<count($this->m_dataChart->m_arrAttributes);$j++)
			{
				$strAttribute =$this->m_dataChart->m_arrAttributes[$j];
				fwrite($this->m_fileSVG,"newText = svgdoc.createTextNode(\"" . $this->m_dataChart->m_arrObjects[$i]->$strAttribute. "\");\n");
				fwrite($this->m_fileSVG,"svgobj =svgdoc.getElementById('$strAttribute');\n");
				fwrite($this->m_fileSVG,"svgobj.replaceChild(newText,svgobj.getFirstChild());\n");
			}
			fwrite($this->m_fileSVG,"newText = svgdoc.createTextNode(\"" . $this->m_dataChart->m_arrObjects[$i]->m_strIndex. "\");\n");
			fwrite($this->m_fileSVG,"svgobj =svgdoc.getElementById('index');\n");
			fwrite($this->m_fileSVG,"svgobj.replaceChild(newText,svgobj.getFirstChild());\n");
			fwrite($this->m_fileSVG, "}\n");
		}
		fwrite($this->m_fileSVG,"]]></script>\n");
	}
}
//************************************************************************
?>
Return current item: Circle Chart using SVG