Posted By

jatkins on 06/16/12


Tagged

css html xhtml chart graph piechart


Versions (?)

JavaScript/XHTML/CSS pie charts


 / Published in: JavaScript
 

Released into the public domain. Not really intended for real-world use (it's a clumsy, inefficient, unaesthetic solution--but it is kind of neat).

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>Pie Chart Generator</title>
  6. <script type="text/javascript">
  7. // <![CDATA[
  8. if(!Object.keys) Object.keys = function(o) { // from http://tokenposts.blogspot.com.au/2012/04/javascript-objectkeys-browser.html
  9. if(o!==Object(o))
  10. throw new TypeError('Object.keys called on a non-object');
  11. var k = [], p;
  12. for (p in o) {
  13. if(Object.prototype.hasOwnProperty.call(o,p))
  14. k.push(p);
  15. }
  16. return k;
  17. };
  18.  
  19. var misc = {
  20. math: {
  21. justNumber: function(stringToClean) {
  22. return parseFloat(stringToClean.toString().replace(/[^0-9\.\-]/g, ''));
  23. },
  24.  
  25. degToRad: function(angleInDegrees) {
  26. return angleInDegrees * Math.PI / 180;
  27. }
  28. },
  29.  
  30. js: {
  31. getRandomColor: function() {
  32. return 'rgb('+Math.round(Math.random()*254)+', '+Math.round(Math.random()*254)+', '+Math.round(Math.random()*254)+')';
  33. }
  34. }
  35. }
  36.  
  37. var pieChart = function(pieName, radius, pieData) {
  38. var pieDiv = document.createElement('div'),
  39. radiusSquared = Math.pow(radius, 2);
  40.  
  41. pieDiv.id = pieName;
  42. pieDiv.className = 'chart';
  43. pieDiv.style.width = radius * 2 + 'px';
  44. pieDiv.style.height = radius * 2 + 'px';
  45. document.body.appendChild(pieDiv);
  46.  
  47. this.renderPoint = function(x, y, pointColor) {
  48. var newPoint = document.createElement('span');
  49. newPoint.style.left = x + radius + 'px';
  50. newPoint.style.top = y + radius + 'px';
  51. newPoint.style.backgroundColor = pointColor;
  52. pieDiv.appendChild(newPoint);
  53. return {x: x+radius, y: y+radius};
  54. };
  55.  
  56. this.renderCircle = function(sparseMatrix) {
  57. var x = -radius;
  58. while(x<radius) {
  59. x++;
  60. y = Math.sqrt(radiusSquared - Math.pow(x, 2));
  61. this.renderPoint(x, y); // for the bottom semicircle
  62. this.renderPoint(x, -y); // for the top semicircle
  63.  
  64. if(!sparseMatrix['x'+x])
  65. sparseMatrix['x'+x] = [];
  66. sparseMatrix['x'+x]['y'+y] = '#000000';
  67. sparseMatrix['x'+x]['y-'+y] = '#000000';
  68. }
  69.  
  70. return sparseMatrix;
  71. };
  72.  
  73. this.rotatePoint = function(origPoint, cosTheta, sinTheta) {
  74. return {x: origPoint.x*cosTheta - origPoint.y*sinTheta, y: origPoint.x*sinTheta + origPoint.y*cosTheta};
  75. };
  76.  
  77. this.renderLine = function(startPoint, endPoint, rotateBy, lineColor, sparseMatrix) { // render a straight line (y=mx+c)
  78. var rotateByInRadians = misc.math.degToRad(rotateBy), cosTheta, sinTheta;
  79. cosTheta = Math.cos(rotateByInRadians);
  80. sinTheta = Math.sin(rotateByInRadians);
  81.  
  82. startPoint = this.rotatePoint(startPoint, cosTheta, sinTheta);
  83. endPoint = this.rotatePoint(endPoint, cosTheta, sinTheta);
  84.  
  85. var width = Math.abs(endPoint.x-startPoint.x), height = Math.abs(endPoint.y-startPoint.y);
  86. if((width>height&&startPoint.x>endPoint.x)||(height>width&&startPoint.y>endPoint.y)) {
  87. var tempPoint = startPoint;
  88. startPoint = endPoint;
  89. endPoint = tempPoint;
  90. }
  91.  
  92. var gradient = (endPoint.y-startPoint.y)/(endPoint.x-startPoint.x);
  93. if(Math.abs(gradient)==Number.POSITIVE_INFINITY)
  94. gradient = 0;
  95. var yIntercept = startPoint.y - gradient * startPoint.x, xCoord, yCoord;
  96. if(height>width) {
  97. for(var i=startPoint.y;i<endPoint.y;i++) {
  98. xCoord = gradient == 0 ? startPoint.x : (i-yIntercept)/gradient;
  99. this.renderPoint(xCoord, i, lineColor);
  100. if(!sparseMatrix['x'+xCoord])
  101. sparseMatrix['x'+xCoord] = [];
  102. sparseMatrix['x'+xCoord]['y'+i] = lineColor;
  103. }
  104. }
  105. else {
  106. for(var i=startPoint.x;i<endPoint.x;i++) {
  107. yCoord = gradient * i + yIntercept;
  108. this.renderPoint(i, yCoord, lineColor);
  109. if(!sparseMatrix['x'+i])
  110. sparseMatrix['x'+i] = [];
  111. sparseMatrix['x'+i]['y'+yCoord] = lineColor;
  112. }
  113. }
  114.  
  115. return sparseMatrix;
  116. };
  117.  
  118. // draw sectors
  119. var lineColor = misc.js.getRandomColor(), currentAngle = 0, sectorAngles = [], dataSum = 0, sectorColors = [];
  120.  
  121. for(var i=0;i<pieData.length;i++)
  122. dataSum += pieData[i][1];
  123.  
  124. var cumulativeAngle = 0, currentAngle, currentColor, pieSparseMatrix = [];
  125. for(var i=0;i<pieData.length;i++) {
  126. currentColor = misc.js.getRandomColor();
  127. currentAngle = Math.round(pieData[i][1]/dataSum*360);
  128. cumulativeAngle += currentAngle;
  129. pieSparseMatrix = this.renderLine({x: 0, y: -radius}, {x: 0, y: 0}, cumulativeAngle, currentColor, pieSparseMatrix);
  130. }
  131. var pieLegend = document.createElement('ul');
  132. pieLegend.style.left = radius*2 + 'px';
  133. for(var i=0;i<pieData.length;i++) {
  134. var newLegendLI = document.createElement('li'), newLegendBlock = document.createElement('span');
  135. newLegendLI.style.color = sectorColors[i];
  136. newLegendLI.appendChild(document.createTextNode(pieData[i][0]));
  137. pieLegend.appendChild(newLegendLI);
  138. }
  139. pieDiv.appendChild(pieLegend);
  140.  
  141. pieSparseMatrix = this.renderCircle(pieSparseMatrix);
  142.  
  143. /*var sMatColNames = Object.keys(pieSparseMatrix), sMatRowNames = [], sMatOutput = '';
  144. var k;
  145. for(var j=0;j<sMatColNames.length;j++) {
  146. sMatRowNames = Object.keys(pieSparseMatrix[sMatColNames[j]]);
  147. for(k=0;k<sMatRowNames.length;k++) {
  148. this.renderPoint(sMatColNames[j].substring(1) - 10, sMatRowNames[k].substring(1) - 10, pieSparseMatrix[sMatColNames[j]][sMatRowNames[k]]);
  149. }
  150. }
  151. alert(sMatOutput);*/
  152. };
  153.  
  154. function initPie() {
  155. var myPieChart = new pieChart('myPieChart', 100, [['WinXP',500],['Win7',1200],['WinVista',500],['Win8',800],['Win95',900]]);
  156. }
  157. // ]]>
  158. </script>
  159. <style type="text/css">
  160. <!--
  161. div.chart {
  162. position: relative;
  163. border: 1px solid #d3d3d3;
  164. }
  165.  
  166. div.chart span {
  167. display: block;
  168. width: 2px;
  169. height: 2px;
  170. background: #000000;
  171. position: absolute;
  172. }
  173.  
  174. div.chart ul {
  175. list-style: square;
  176. position: absolute;
  177. top: 0px;
  178. }
  179.  
  180. div.chart ul li {
  181. list-style: square;
  182. }
  183. -->
  184. </style>
  185. </head>
  186. <body onload="initPie();">
  187. <h1>Pie Chart Generator</h1>
  188. </body>
  189. </html>
  190. <!--
  191. polygon fill algorithm
  192. ======================
  193.  
  194. create a sparse matrix representing the bitmap of the polygon to be filled
  195. running col-by-col through the sparse matrix, do this:
  196. start filling from the cell below the first pixel in the sparse matrix of the target color
  197. continue filling until you reach the last pixel in the column of the target color
  198. -->
  199. <script>
  200. var sMatColNames = Object.keys(pieSparseMatrix), sMatRowNames = [], sMatOutput = '';
  201. var k;
  202. for(var j=0;j<sMatColNames.length;j++) {
  203. sMatRowNames = Object.keys(pieSparseMatrix[sMatColNames[j]]);
  204. for(k=0;k<sMatRowNames.length;k++) {
  205. this.renderPoint(sMatColNames[j].substring(1) - 10, sMatRowNames[k].substring(1) - 10, pieSparseMatrix[sMatColNames[j]][sMatRowNames[k]]);
  206. }
  207. }
  208. alert(sMatOutput);
  209. </script>

Report this snippet  

You need to login to post a comment.