/ 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).
Expand |
Embed | Plain Text
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Pie Chart Generator</title> <script type="text/javascript"> // <![CDATA[ if(!Object.keys) Object.keys = function(o) { // from http://tokenposts.blogspot.com.au/2012/04/javascript-objectkeys-browser.html if(o!==Object(o)) throw new TypeError('Object.keys called on a non-object'); var k = [], p; for (p in o) { if(Object.prototype.hasOwnProperty.call(o,p)) k.push(p); } return k; }; var misc = { math: { justNumber: function(stringToClean) { return parseFloat(stringToClean.toString().replace(/[^0-9\.\-]/g, '')); }, degToRad: function(angleInDegrees) { return angleInDegrees * Math.PI / 180; } }, js: { getRandomColor: function() { return 'rgb('+Math.round(Math.random()*254)+', '+Math.round(Math.random()*254)+', '+Math.round(Math.random()*254)+')'; } } } var pieChart = function(pieName, radius, pieData) { var pieDiv = document.createElement('div'), radiusSquared = Math.pow(radius, 2); pieDiv.id = pieName; pieDiv.className = 'chart'; pieDiv.style.width = radius * 2 + 'px'; pieDiv.style.height = radius * 2 + 'px'; document.body.appendChild(pieDiv); this.renderPoint = function(x, y, pointColor) { var newPoint = document.createElement('span'); newPoint.style.left = x + radius + 'px'; newPoint.style.top = y + radius + 'px'; newPoint.style.backgroundColor = pointColor; pieDiv.appendChild(newPoint); return {x: x+radius, y: y+radius}; }; this.renderCircle = function(sparseMatrix) { var x = -radius; while(x<radius) { x++; y = Math.sqrt(radiusSquared - Math.pow(x, 2)); this.renderPoint(x, y); // for the bottom semicircle this.renderPoint(x, -y); // for the top semicircle if(!sparseMatrix['x'+x]) sparseMatrix['x'+x] = []; sparseMatrix['x'+x]['y'+y] = '#000000'; sparseMatrix['x'+x]['y-'+y] = '#000000'; } return sparseMatrix; }; this.rotatePoint = function(origPoint, cosTheta, sinTheta) { return {x: origPoint.x*cosTheta - origPoint.y*sinTheta, y: origPoint.x*sinTheta + origPoint.y*cosTheta}; }; this.renderLine = function(startPoint, endPoint, rotateBy, lineColor, sparseMatrix) { // render a straight line (y=mx+c) var rotateByInRadians = misc.math.degToRad(rotateBy), cosTheta, sinTheta; cosTheta = Math.cos(rotateByInRadians); sinTheta = Math.sin(rotateByInRadians); startPoint = this.rotatePoint(startPoint, cosTheta, sinTheta); endPoint = this.rotatePoint(endPoint, cosTheta, sinTheta); var width = Math.abs(endPoint.x-startPoint.x), height = Math.abs(endPoint.y-startPoint.y); if((width>height&&startPoint.x>endPoint.x)||(height>width&&startPoint.y>endPoint.y)) { var tempPoint = startPoint; startPoint = endPoint; endPoint = tempPoint; } var gradient = (endPoint.y-startPoint.y)/(endPoint.x-startPoint.x); if(Math.abs(gradient)==Number.POSITIVE_INFINITY) gradient = 0; var yIntercept = startPoint.y - gradient * startPoint.x, xCoord, yCoord; if(height>width) { for(var i=startPoint.y;i<endPoint.y;i++) { xCoord = gradient == 0 ? startPoint.x : (i-yIntercept)/gradient; this.renderPoint(xCoord, i, lineColor); if(!sparseMatrix['x'+xCoord]) sparseMatrix['x'+xCoord] = []; sparseMatrix['x'+xCoord]['y'+i] = lineColor; } } else { for(var i=startPoint.x;i<endPoint.x;i++) { yCoord = gradient * i + yIntercept; this.renderPoint(i, yCoord, lineColor); if(!sparseMatrix['x'+i]) sparseMatrix['x'+i] = []; sparseMatrix['x'+i]['y'+yCoord] = lineColor; } } return sparseMatrix; }; // draw sectors var lineColor = misc.js.getRandomColor(), currentAngle = 0, sectorAngles = [], dataSum = 0, sectorColors = []; for(var i=0;i<pieData.length;i++) dataSum += pieData[i][1]; var cumulativeAngle = 0, currentAngle, currentColor, pieSparseMatrix = []; for(var i=0;i<pieData.length;i++) { currentColor = misc.js.getRandomColor(); currentAngle = Math.round(pieData[i][1]/dataSum*360); cumulativeAngle += currentAngle; pieSparseMatrix = this.renderLine({x: 0, y: -radius}, {x: 0, y: 0}, cumulativeAngle, currentColor, pieSparseMatrix); } var pieLegend = document.createElement('ul'); pieLegend.style.left = radius*2 + 'px'; for(var i=0;i<pieData.length;i++) { var newLegendLI = document.createElement('li'), newLegendBlock = document.createElement('span'); newLegendLI.style.color = sectorColors[i]; newLegendLI.appendChild(document.createTextNode(pieData[i][0])); pieLegend.appendChild(newLegendLI); } pieDiv.appendChild(pieLegend); pieSparseMatrix = this.renderCircle(pieSparseMatrix); /*var sMatColNames = Object.keys(pieSparseMatrix), sMatRowNames = [], sMatOutput = ''; var k; for(var j=0;j<sMatColNames.length;j++) { sMatRowNames = Object.keys(pieSparseMatrix[sMatColNames[j]]); for(k=0;k<sMatRowNames.length;k++) { this.renderPoint(sMatColNames[j].substring(1) - 10, sMatRowNames[k].substring(1) - 10, pieSparseMatrix[sMatColNames[j]][sMatRowNames[k]]); } } alert(sMatOutput);*/ }; function initPie() { var myPieChart = new pieChart('myPieChart', 100, [['WinXP',500],['Win7',1200],['WinVista',500],['Win8',800],['Win95',900]]); } // ]]> </script> <style type="text/css"> <!-- div.chart { position: relative; border: 1px solid #d3d3d3; } div.chart span { display: block; width: 2px; height: 2px; background: #000000; position: absolute; } div.chart ul { list-style: square; position: absolute; top: 0px; } div.chart ul li { list-style: square; } --> </style> </head> <body onload="initPie();"> <h1>Pie Chart Generator</h1> </body> </html> <!-- polygon fill algorithm ====================== create a sparse matrix representing the bitmap of the polygon to be filled running col-by-col through the sparse matrix, do this: start filling from the cell below the first pixel in the sparse matrix of the target color continue filling until you reach the last pixel in the column of the target color --> <script> var sMatColNames = Object.keys(pieSparseMatrix), sMatRowNames = [], sMatOutput = ''; var k; for(var j=0;j<sMatColNames.length;j++) { sMatRowNames = Object.keys(pieSparseMatrix[sMatColNames[j]]); for(k=0;k<sMatRowNames.length;k++) { this.renderPoint(sMatColNames[j].substring(1) - 10, sMatRowNames[k].substring(1) - 10, pieSparseMatrix[sMatColNames[j]][sMatRowNames[k]]); } } alert(sMatOutput); </script>
You need to login to post a comment.
