Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Hope to keep the canvas area small enough to prevent scrolling. Will need to revise some of the calculations. Please test!! git-svn-id: https://xerteonlinetoolkits.googlecode.com/svn/trunk@583 912cdd6b-5c7d-d5a7-a2ba-d0f0cdb91641
- Loading branch information
1 parent
c589978
commit 0747a00
Showing
1 changed file
with
325 additions
and
0 deletions.
There are no files selected for viewing
325 changes: 325 additions & 0 deletions
325
modules/xerte/parent_templates/Nottingham/models_html5/chart.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,325 @@ | ||
<script type="text/javascript"> | ||
// ----------------------------------------------------------------------------------------- | ||
// All drawing code based on Actionscript routines by Ric Ewing (ric@formequalsfunction.com) | ||
// ----------------------------------------------------------------------------------------- | ||
|
||
// pageChanged & sizeChanged functions are needed in every model file | ||
// other functions for model should also be in here to avoid conflicts | ||
var chart = new function() { | ||
var allSeries; | ||
|
||
// function called every time the page is viewed after it has initially loaded | ||
this.pageChanged = function() { | ||
|
||
}; | ||
|
||
// function called every time the size of the LO is changed | ||
this.sizeChanged = function() { | ||
|
||
}; | ||
|
||
this.doAxesAndLabels = function(canvas, w, w1, yMin, yMax, scalar, hMax) { | ||
canvas.strokeStyle = '#000000'; | ||
canvas.fillStyle = '#000000'; | ||
canvas.beginPath(); | ||
canvas.moveTo(0,30 + allSeries.length * 20); | ||
canvas.lineTo(0,445); | ||
canvas.moveTo(-5,440); | ||
canvas.lineTo(350,440); | ||
canvas.fill(); | ||
canvas.stroke(); | ||
|
||
//draw the legend | ||
canvas.beginPath(); | ||
for (var i = 0;i < allSeries.length; i++) { | ||
canvas.strokeStyle = allSeries[i].colour; | ||
canvas.fillStyle = allSeries[i].colour; | ||
canvas.fillRect(-50, 23 + i * 20, 12, 12); | ||
canvas.fill() | ||
canvas.stroke(); | ||
|
||
canvas.fillStyle = '#000000'; | ||
canvas.textBaseline = "top"; | ||
canvas.fillText(allSeries[i].name, -30, 22 + i * 20); | ||
} | ||
|
||
//draw the x labels | ||
for (var i = 0; i < allSeries[0].data.length; i++) { | ||
canvas.fillStyle = '#000000'; | ||
canvas.textBaseline = "top"; | ||
canvas.fillText(allSeries[0].data[i].x, w * (i + 0.5) - 5, 444); | ||
} | ||
|
||
//draw the y labels | ||
canvas.fillText(yMin, -25, 434); | ||
canvas.fillText(yMax, -25, 434-hMax); | ||
}; | ||
|
||
this.doStackedBar = function(canvas, w, hMax) { | ||
var cumH = []; | ||
|
||
for (i = 0; i < allSeries[0].data.length; i++) { | ||
cumH[i] = 0; | ||
} | ||
|
||
var tempCH, maxCH = 0; | ||
//find total colum height | ||
for (i = 0; i < allSeries[0].data.length; i++) { //for each dimension | ||
tempCH = 0; | ||
for (j = 0; j < allSeries.length; j++) { | ||
tempCH += allSeries[j].data[i].y; | ||
} | ||
} | ||
if (tempCH > maxCH) { | ||
maxCH = tempCH; | ||
} | ||
|
||
var scalar = hMax / maxCH; | ||
|
||
var tempH | ||
canvas.lineWidth = 2; | ||
for (i = 0; i < allSeries.length; i++) { //for each series | ||
canvas.strokeStyle = allSeries[i].colour; | ||
canvas.fillStyle = allSeries[i].colour; | ||
for (j = 0; j < allSeries[i].data.length; j++) { | ||
tempH = allSeries[i].data[j].y; | ||
canvas.fillRect(w * j, 440 - cumH[j] * scalar, w * 0.9 , -tempH * scalar); | ||
cumH[j] += tempH; | ||
} | ||
canvas.fill(); | ||
canvas.stroke(); | ||
} | ||
}; | ||
|
||
this.doBar = function(canvas, w, w1, yMin, scalar) { | ||
var tempH; | ||
canvas.lineWidth = 2; | ||
for (var i=0; i<allSeries.length; i++) { | ||
canvas.strokeStyle = allSeries[i].colour; | ||
canvas.fillStyle = allSeries[i].colour; | ||
for (var j=0; j<allSeries[i].data.length; j++) { | ||
if (!isNaN(allSeries[i].data[j].y)) { | ||
tempH = (allSeries[i].data[j].y - yMin) * scalar; | ||
canvas.fillRect(w*j+i*w1, 440, w*0.9 / allSeries.length, -tempH); | ||
} | ||
} | ||
canvas.fill(); | ||
canvas.stroke(); | ||
} | ||
}; | ||
|
||
this.doLine = function(canvas, w, yMin, scalar) { | ||
canvas.lineWidth = 2; | ||
for (var i=0; i<allSeries.length; i++) { | ||
canvas.beginPath(); | ||
canvas.strokeStyle = allSeries[i].colour; | ||
canvas.moveTo(w/2, 440 - (allSeries[i].data[0].y - yMin) * scalar); | ||
for (var j=0; j<allSeries[i].data.length; j++) { | ||
if (!isNaN(allSeries[i].data[j].y)) { | ||
canvas.lineTo(w*j + w/2, 440 - (allSeries[i].data[j].y - yMin) * scalar); | ||
} | ||
} | ||
canvas.stroke(); | ||
} | ||
}; | ||
|
||
this.doPie = function(canvas) { | ||
var hexToRgb = function (hex) { | ||
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); | ||
return result ? { | ||
r: parseInt(result[1], 16), | ||
g: parseInt(result[2], 16), | ||
b: parseInt(result[3], 16) | ||
} : null; | ||
}; | ||
|
||
var rgbToHex = function (r, g, b) { | ||
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); | ||
}; | ||
|
||
// build the colour array | ||
var colours = []; | ||
var rgb = hexToRgb(allSeries[0].colour); | ||
for (var i = 0; i < allSeries[0].data.length; i++) { | ||
colours.push(rgbToHex( | ||
parseInt(rgb.r + i * (255 - rgb.r)/allSeries[0].data.length), | ||
parseInt(rgb.g + i * (255 - rgb.g)/allSeries[0].data.length), | ||
parseInt(rgb.b + i * (255 - rgb.b)/allSeries[0].data.length) | ||
)); | ||
} | ||
|
||
var colOff = 100 / allSeries.length; | ||
for (var i = 0; i < allSeries[0].data.length; i++) { | ||
canvas.strokeStyle = '#000000'; | ||
canvas.fillStyle = colours[i]; | ||
canvas.lineWidth = 1; | ||
canvas.fillRect(-50, 22 + i * 20, 12, 12); | ||
canvas.strokeRect(-50, 22 + i * 20, 12, 12); | ||
canvas.fill(); | ||
canvas.stroke(); | ||
canvas.textBaseline = "top"; | ||
canvas.fillStyle = '#000000'; | ||
canvas.fillText(allSeries[0].data[i].y, -30, 22 + i * 20); | ||
} | ||
|
||
///draw chart | ||
for (var i = 0; i < 1; i++) { //for first series | ||
//get the total for this series | ||
var sT = 0; | ||
for (j = 0; j < allSeries[i].data.length; j++) { | ||
sT += allSeries[i].data[j].y; | ||
} | ||
|
||
var theta, exTheta = 0; | ||
for (var j = 0; j < allSeries[i].data.length; j++) { //draw each segment... | ||
theta = Number(allSeries[i].data[j].y) / sT * 360; | ||
this.drawWedge(canvas, 170, 260, 150 - i * (150 / allSeries.length), theta, exTheta, colours[j]); | ||
exTheta += theta; | ||
} | ||
} | ||
}; | ||
|
||
this.drawWedge = function(canvas, x, y, radius, arc, r, colour) { | ||
canvas.save(); | ||
canvas.translate(x, y); | ||
canvas.rotate( -r * Math.PI / 180); | ||
canvas.fillStyle = colour; | ||
canvas.strokeStyle = colour; | ||
canvas.beginPath(); | ||
canvas.moveTo(0, 0); | ||
var segAngle, theta, angle, angleMid, segs, ax, ay, bx, by, cx, cy; | ||
if (Math.abs(arc) > 360) { | ||
arc = 360; | ||
} | ||
segs = Math.ceil(Math.abs(arc) / 45); | ||
segAngle = arc / segs; | ||
theta = - Math.PI * segAngle / 180; | ||
angle = - Math.PI * 0 / 180; | ||
if (segs > 0) { | ||
ax = Math.cos(0 * Math.PI / 180) * radius; | ||
ay = Math.sin(-0 * Math.PI / 180) * radius; | ||
canvas.lineTo(ax, ay); | ||
for (var i = 0; i < segs; i++) { | ||
angle += theta; | ||
angleMid = angle - theta / 2; | ||
bx = Math.cos(angle) * radius; | ||
by = Math.sin(angle) * radius; | ||
cx = Math.cos(angleMid) * radius / Math.cos(theta / 2); | ||
cy = Math.sin(angleMid) * radius / Math.cos(theta / 2); | ||
canvas.quadraticCurveTo(cx, cy, bx, by); | ||
} | ||
canvas.lineTo(0, 0); | ||
} | ||
canvas.closePath(); | ||
canvas.fill(); | ||
canvas.globalAlpha = 100; | ||
canvas.stroke(); | ||
canvas.restore(); | ||
}; | ||
|
||
this.init = function() { | ||
var $pageContents = $("#pageContents"); | ||
var $textHolder = $("#textHolder"); | ||
var $panel = $("#pageContents .panel"); | ||
var $chartTitle = $("#chartTitle"); | ||
var chartHolder = document.getElementById('chartHolder'); | ||
|
||
$textHolder.html(x_addLineBreaks(x_currentPageXML.getAttribute("text"))); | ||
$chartTitle.html(x_currentPageXML.getAttribute("chartTitle")); | ||
|
||
allSeries = []; | ||
var yMin, yMax; | ||
var series = $(x_currentPageXML).children(); | ||
if (series.length == 0) { | ||
// There are no series | ||
} | ||
else { | ||
yMin = 1000000, yMax = 0; | ||
$(x_currentPageXML).children().each(function () { | ||
var name = this.getAttribute("name"); | ||
var dataString = this.getAttribute("data"); | ||
var colour = this.getAttribute("colour"); | ||
if (colour.substring(0, 2) == '0x') { // hex value | ||
colour = '#' + Array(9-colour.length).join('0') + colour.substring(2); | ||
} | ||
|
||
var dataPair, dataPairs = dataString.split('||'); | ||
var data = []; | ||
for (var i=0; i<dataPairs.length; i++) { | ||
dataPair = dataPairs[i].split('|'); | ||
data.push({"x":parseInt(dataPair[0]), "y":parseInt(dataPair[1])}); | ||
if (!isNaN(parseInt(dataPair[1]))) { | ||
yMax = Math.max(yMax, parseInt(dataPair[1])); | ||
yMin = Math.floor(Math.min(yMin, parseInt(dataPair[1])) * 0.9); | ||
} | ||
} | ||
allSeries.push({"name":name, "colour": colour, "data":data}); | ||
}); | ||
} | ||
|
||
var hMax = 410 - allSeries.length * 20; | ||
var scalar = hMax / (yMax - yMin); | ||
var w = 350 / allSeries[0].data.length; | ||
var w1 = w * 0.9 / allSeries.length; | ||
|
||
chartHolder.width = 410; | ||
chartHolder.height = 460; | ||
|
||
chartHolder.getContext("2d").translate(60, 0); | ||
|
||
switch (x_currentPageXML.getAttribute("chartType")) { | ||
case "stacked bar": | ||
this.doStackedBar(chartHolder.getContext("2d"), w, hMax); | ||
break; | ||
case "pie": | ||
this.doPie(chartHolder.getContext("2d")); | ||
break; | ||
case "bar": | ||
this.doBar(chartHolder.getContext("2d"), w, w1, yMin, scalar); | ||
break; | ||
case "line": | ||
this.doLine(chartHolder.getContext("2d"), w, yMin, scalar); | ||
} | ||
|
||
if (x_currentPageXML.getAttribute("chartType") != "pie") { | ||
this.doAxesAndLabels(chartHolder.getContext("2d"), w, w1, yMin, yMax, scalar, hMax) | ||
} | ||
|
||
if (x_currentPageXML.getAttribute("align") != "right") { | ||
$panel.addClass("x_floatRight"); | ||
} else { | ||
$panel.addClass("x_floatLeft"); | ||
} | ||
|
||
// call this function in every model once everything's loaded | ||
x_pageLoaded(); | ||
}; | ||
}; | ||
|
||
chart.init(); | ||
|
||
</script> | ||
|
||
<style type="text/css"> | ||
|
||
#chartTitle { | ||
font-weight: bold; | ||
text-align: center; | ||
} | ||
|
||
</style> | ||
|
||
<div id="pageContents"> | ||
|
||
<div id="tableHolder" class="mobileAlign"> <!-- this tag is only used when viewed on mobiles to change layout --> | ||
<div class="panel inline"> | ||
<div id="chartTitle"></div> | ||
<canvas id="chartHolder"></canvas> | ||
</div> | ||
</div> | ||
|
||
<div id="textHolder"> | ||
|
||
</div> | ||
|
||
</div> |