Index: bower_components/chartnewjs/ChartNew.js |
diff --git a/bower_components/chartnewjs/ChartNew.js b/bower_components/chartnewjs/ChartNew.js |
deleted file mode 100644 |
index 6c756e6e647a101f9c0dc5e811a893ab9bb795c0..0000000000000000000000000000000000000000 |
--- a/bower_components/chartnewjs/ChartNew.js |
+++ /dev/null |
@@ -1,6491 +0,0 @@ |
-/* |
- * ChartNew.js |
- * |
- * Vancoppenolle Francois - January 2014 |
- * francois.vancoppenolle@favomo.be |
- * |
- * Source location : http:\\www.favomo.be\graphjs |
- * GitHub community : https://github.com/FVANCOP/ChartNew.js |
- * |
- * This file is an adaptation of the chart.js source developped by Nick Downie (2013) |
- * https://github.com/nnnick/Chart.js |
- * |
- * new charts |
- * |
- * horizontalBar |
- * horizontalStackedBar |
- * |
- * Added items : |
- * |
- * Title |
- * Subtitle |
- * X Axis Label |
- * Y Axis Label |
- * Unit Label |
- * Y Axis on the right and/or the left |
- * Annotates |
- * canvas Border |
- * Legend |
- * Footnote |
- * crossText |
- * graphMin / graphMax |
- * logarithmic y-axis (for line and bar) |
- * rotateLabels |
- * and lot of others... |
- * |
- */ |
-// non standard functions; |
-if (typeof String.prototype.trim !== 'function') { |
- String.prototype.trim = function() { |
- return this.replace(/^\s+|\s+$/g, ''); |
- } |
-}; |
-if (!Array.prototype.indexOf) { |
- Array.prototype.indexOf = function(searchElement /*, fromIndex */ ) { |
- "use strict"; |
- if (this == null) { |
- throw new TypeError(); |
- } |
- var t = Object(this); |
- var len = t.length >>> 0; |
- if (len === 0) { |
- return -1; |
- } |
- var n = 0; |
- if (arguments.length > 0) { |
- n = Number(arguments[1]); |
- if (n != n) { // shortcut for verifying if it's NaN |
- n = 0; |
- } else if (n != 0 && n != Infinity && n != -Infinity) { |
- n = (n > 0 || -1) * Math.floor(Math.abs(n)); |
- } |
- } |
- if (n >= len) { |
- return -1; |
- } |
- var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); |
- for (; k < len; k++) { |
- if (k in t && t[k] === searchElement) { |
- return k; |
- } |
- } |
- return -1; |
- } |
-}; |
-var charJSPersonalDefaultOptions = {} |
-var charJSPersonalDefaultOptionsLine = {} |
-var charJSPersonalDefaultOptionsRadar = {} |
-var charJSPersonalDefaultOptionsPolarArea = {} |
-var charJSPersonalDefaultOptionsPie = {} |
-var charJSPersonalDefaultOptionsDoughnut = {} |
-var charJSPersonalDefaultOptionsBar = {} |
-var charJSPersonalDefaultOptionsStackedBar = {} |
-var charJSPersonalDefaultOptionsHorizontalBar = {} |
-var charJSPersonalDefaultOptionsHorizontalStackedBar = {} |
- ///////// FUNCTIONS THAN CAN BE USED IN THE TEMPLATES /////////////////////////////////////////// |
- |
-function roundToWithThousands(config, num, place) { |
- var newval = 1 * unFormat(config, num); |
- if (typeof(newval) == "number" && place != "none") { |
- if (place <= 0) { |
- var roundVal = -place; |
- newval = +(Math.round(newval + "e+" + roundVal) + "e-" + roundVal); |
- } else { |
- var roundVal = place; |
- var divval = "1e+" + roundVal; |
- newval = +(Math.round(newval / divval)) * divval; |
- } |
- } |
- newval = fmtChartJS(config, newval, "none"); |
- return (newval); |
-}; |
- |
-function unFormat(config, num) { |
- if ((config.decimalSeparator != "." || config.thousandSeparator != "") && typeof(num) == "string") { |
- var v1 = "" + num; |
- if (config.thousandSeparator != "") { |
- while (v1.indexOf(config.thousandSeparator) >= 0) v1 = "" + v1.replace(config.thousandSeparator, ""); |
- } |
- if (config.decimalSeparator != ".") v1 = "" + v1.replace(config.decimalSeparator, ".") |
- // v1=fmtChartJS(config,1*roundToWithThousands(1*v1,place),"none") |
- return 1 * v1; |
- } else { |
- return num; |
- } |
-}; |
-///////// ANNOTATE PART OF THE SCRIPT /////////////////////////////////////////// |
-/******************************************************************************** |
-Copyright (C) 1999 Thomas Brattli |
-This script is made by and copyrighted to Thomas Brattli |
-Visit for more great scripts. This may be used freely as long as this msg is intact! |
-I will also appriciate any links you could give me. |
-Distributed by Hypergurl |
-********************************************************************************/ |
-var cachebis = {}; |
- |
-function fmtChartJSPerso(config, value, fmt) { |
- switch (fmt) { |
- case "SampleJS_Format": |
- if (typeof(value) == "number") return_value = "My Format : " + value.toString() + " $"; |
- else return_value = value + "XX"; |
- break; |
- case "Change_Month": |
- if (typeof(value) == "string") return_value = value.toString() + " 2014"; |
- else return_value = value.toString() + "YY"; |
- break; |
- default: |
- return_value = value; |
- break; |
- } |
- return (return_value); |
-}; |
- |
-function fmtChartJS(config, value, fmt) { |
- var return_value; |
- if (fmt == "notformatted") { |
- return_value = value; |
- } else if (fmt == "none" && typeof(value) == "number") { |
- if (config.roundNumber != "none") { |
- if (config.roundNumber <= 0) { |
- var roundVal = -config.roundNumber; |
- value = +(Math.round(value + "e+" + roundVal) + "e-" + roundVal); |
- } else { |
- var roundVal = config.roundNumber; |
- var divval = "1e+" + roundVal; |
- value = +(Math.round(value / divval)) * divval; |
- } |
- } |
- if (config.decimalSeparator != "." || config.thousandSeparator != "") { |
- return_value = value.toString().replace(/\./g, config.decimalSeparator); |
- if (config.thousandSeparator != "") { |
- var part1 = return_value; |
- var part2 = ""; |
- var posdec = part1.indexOf(config.decimalSeparator); |
- if (posdec >= 0) { |
- part2 = part1.substring(posdec + 1, part1.length); |
- part2 = part2.split('').reverse().join(''); // reverse string |
- part1 = part1.substring(0, posdec); |
- } |
- part1 = part1.toString().replace(/\B(?=(\d{3})+(?!\d))/g, config.thousandSeparator); |
- // part2=part2.toString().replace(/\B(?=(\d{3})+(?!\d))/g, config.thousandSeparator); |
- part2 = part2.split('').reverse().join(''); // reverse string |
- return_value = part1 |
- if (part2 != "") return_value = return_value + config.decimalSeparator + part2; |
- } |
- } else return_value = value; |
- } else if (fmt != "none" && fmt != "notformatted") { |
- return_value = fmtChartJSPerso(config, value, fmt); |
- } else { |
- return_value = value; |
- } |
- return (return_value); |
-}; |
- |
-function addParameters2Function(data, fctName, fctList) { |
- var mathFunctions = { |
- mean: { |
- data: data.data, |
- datasetNr: data.v11 |
- }, |
- varianz: { |
- data: data.data, |
- datasetNr: data.v11 |
- }, |
- stddev: { |
- data: data.data, |
- datasetNr: data.v11 |
- }, |
- cv: { |
- data: data.data, |
- datasetNr: data.v11 |
- }, |
- median: { |
- data: data.data, |
- datasetNr: data.v11 |
- } |
- }; |
- // difference to current value (v3) |
- dif = false; |
- if (fctName.substr(-3) == "Dif") { |
- fctName = fctName.substr(0, fctName.length - 3); |
- dif = true; |
- } |
- if (typeof eval(fctName) == "function") { |
- var parameter = eval(fctList + "." + fctName); |
- if (dif) { |
- // difference between v3 (current value) and math function |
- return data.v3 - window[fctName](parameter); |
- } |
- return window[fctName](parameter); |
- } |
- return; |
- } |
- //Is a number function |
- |
-function isNumber(n) { |
- return !isNaN(parseFloat(n)) && isFinite(n); |
-}; |
- |
-function tmplbis(str, data) { |
- var mathFunctionList = ["mean", "varianz", "stddev", "cv", "median"]; |
- var regexMath = new RegExp('<%=((?:(?:.*?)\\W)??)((?:' + mathFunctionList.join('|') + ')(?:Dif)?)\\(([0-9]*?)\\)(.*?)%>', 'g'); |
- while (regexMath.test(str)) { |
- str = str.replace(regexMath, function($0, $1, $2, $3, $4) { |
- if ($3) { |
- var rndFac = $3; |
- } else { |
- var rndFac = 2; |
- } |
- var value = addParameters2Function(data, $2, "mathFunctions"); |
- if (isNumber(value)) { |
- return '<%=' + $1 + '' + Math.round(Math.pow(10, rndFac) * value) / Math.pow(10, rndFac) + '' + $4 + '%>'; |
- } |
- return '<%= %>'; |
- }); |
- } |
- // Figure out if we're getting a template, or if we need to |
- // load the template - and be sure to cache the result. |
- // first check if it's can be an id |
- var fn = /^[A-Za-z][-A-Za-z0-9_:.]*$/.test(str) ? cachebis[str] = cachebis[str] || |
- tmplbis(document.getElementById(str).innerHTML) : |
- // Generate a reusable function that will serve as a template |
- // generator (and which will be cached). |
- new Function("obj", |
- "var p=[],print=function(){p.push.apply(p,arguments);};" + |
- // Introduce the data as local variables using with(){} |
- "with(obj){p.push('" + |
- // Convert the template into pure JavaScript |
- str |
- .replace(/[\r\n]/g, "\\n") |
- .replace(/[\t]/g, " ") |
- .split("<%").join("\t") |
- .replace(/((^|%>)[^\t]*)'/g, "$1\r") |
- .replace(/\t=(.*?)%>/g, "',$1,'") |
- .split("\t").join("');") |
- .split("%>").join("p.push('") |
- .split("\r").join("\\'") + "');}return p.join('');"); |
- // Provide some basic currying to the user |
- return data ? fn(data) : fn; |
-}; |
-/** |
- * ctx.prototype |
- * fillText option for canvas Multiline Support |
- * @param text string \n for newline |
- * @param x x position |
- * @param y y position |
- * @param yLevel = "bottom" => last line has this y-Pos [default], = "middle" => the middle line has this y-Pos) |
- * @param lineHeight lineHeight |
- */ |
-CanvasRenderingContext2D.prototype.fillTextMultiLine = function(text, x, y, yLevel, lineHeight) { |
- var lines = ("" + text).split("\n"); |
- // if its one line => in the middle |
- // two lines one above the mid one below etc. |
- if (yLevel == "middle") { |
- y -= ((lines.length - 1) / 2) * lineHeight; |
- } else if (yLevel == "bottom") { // default |
- y -= (lines.length - 1) * lineHeight; |
- } |
- for (var i = 0; i < lines.length; i++) { |
- this.fillText(lines[i], x, y); |
- y += lineHeight; |
- } |
-} |
-CanvasRenderingContext2D.prototype.measureTextMultiLine = function(text, lineHeight) { |
- var textWidth = 0; |
- var lg; |
- var lines = ("" + text).split("\n"); |
- var textHeight = lines.length * lineHeight; |
- // if its one line => in the middle |
- // two lines one above the mid one below etc. |
- for (var i = 0; i < lines.length; i++) { |
- lg = this.measureText(lines[i]).width; |
- if (lg > textWidth) textWidth = lg; |
- } |
- return { |
- textWidth: textWidth, |
- textHeight: textHeight |
- }; |
-} |
-cursorDivCreated = false; |
- |
-function createCursorDiv() { |
- if (cursorDivCreated == false) { |
- var div = document.createElement('divCursor'); |
- div.id = 'divCursor'; |
- div.style.position = 'absolute'; |
- document.body.appendChild(div); |
- cursorDivCreated = true; |
- } |
-}; |
- |
-initChartJsResize = false; |
-var jsGraphResize = new Array(); |
- |
-function addResponsiveChart(id,ctx,data,config) { |
- initChartResize(); |
- var newSize=resizeGraph(ctx,config); |
- |
- if(typeof ctx.prevWidth != "undefined") { |
- resizeCtx(ctx,newSize.newWidth,newSize.newHeight); |
- ctx.prevWidth=newSize.newWidth; |
- } |
- ctx.prevWidth=newSize.newWidth; |
- ctx.prevHeight=newSize.newHeight; |
- jsGraphResize[jsGraphResize.length]= [id,ctx.tpchart,ctx,data,config]; |
-}; |
- |
-function initChartResize() { |
- if(initChartJsResize==false) { |
- window.addEventListener("resize", chartJsResize); |
- } |
-}; |
- |
-function getMaximumWidth(domNode){ |
- var container = domNode.parentNode; |
- // TODO = check cross browser stuff with this. |
- return container.clientWidth; |
-}; |
- |
-function getMaximumHeight(domNode){ |
- var container = domNode.parentNode; |
- // TODO = check cross browser stuff with this. |
- return container.clientHeight; |
-}; |
- |
- |
-function resizeCtx(ctx,newWidth,newHeight) |
-{ |
- if (window.devicePixelRatio) { // Retina devine |
- |
- ctx.canvas.style.width = newWidth/window.devicePixelRatio + "px"; |
- ctx.canvas.style.height = newHeight/window.devicePixelRatio + "px"; |
- ctx.canvas.height = newHeight/window.devicePixelRatio * window.devicePixelRatio; |
- ctx.canvas.width = newWidth/window.devicePixelRatio * window.devicePixelRatio; |
- ctx.scale(window.devicePixelRatio, window.devicePixelRatio); |
- } else { |
- ctx.canvas.height = newHeight ; |
- ctx.canvas.width = newWidth; |
- } |
-} |
- |
-function resizeGraph(ctx,config) { |
- if(typeof config.maintainAspectRatio == "undefined")config.maintainAspectRatio=true; |
- var canvas = ctx.canvas; |
- if(typeof ctx.aspectRatio == "undefined") { |
- ctx.aspectRatio = canvas.width / canvas.height; |
- } |
- var newWidth = getMaximumWidth(canvas); |
- var newHeight = config.maintainAspectRatio ? newWidth / ctx.aspectRatio : getMaximumHeight(canvas); |
- return { newWidth : parseInt(newWidth), newHeight : parseInt(newHeight)}; |
-}; |
- |
- |
- |
-function chartJsResize() { |
- for (var i=0;i<jsGraphResize.length;i++) { |
- if(typeof jsGraphResize[i][2].firstPass != "undefined") { |
- if(jsGraphResize[i][2].firstPass == 5)jsGraphResize[i][2].firstPass=6; |
- } |
- subUpdateChart(jsGraphResize[i][2],jsGraphResize[i][3],jsGraphResize[i][4]); |
- } |
-}; |
- |
-function testRedraw(ctx,data,config) { |
- if (ctx.firstPass==2 || ctx.firstPass==4 || ctx.firstPass==9) { |
- ctx.firstPass=6; |
- subUpdateChart(ctx,data,config) ; |
- return true; |
- } else { |
- ctx.firstPass=5; |
- return false; |
- } |
-} |
- |
-function updateChart(ctx,data,config,animation,runanimationcompletefunction) { |
- if (ctx.firstPass==5) |
- { |
- ctx.runanimationcompletefunction=runanimationcompletefunction; |
- if(animation)ctx.firstPass=0; |
- else if (config.responsive) ctx.firstPass=7; |
- else ctx.firstPass=7; |
- subUpdateChart(ctx,data,config) ; |
- |
- } |
-} |
- |
-function subUpdateChart(ctx,data,config) { |
- // ctx.firstPass==undefined => graph never drawn |
- // ctx.firstPass==0 => graph is drawn but need to be redrawn with animation |
- // ctx.firstPass==1 => graph is drawn with animation |
- // ctx.firstPass==2 => graph is in animation but at the end the graph need perhaps to be redrawn; |
- // ctx.firstPass==3 => graph currently drawing without animation; |
- // ctx.firstPass==4 => graph currently drawing without animationb but at the end, the graph need perhaps to be redrawn; |
- // ctx.firstPass==5 => graph is displayed ; |
- // ctx.firstPass==6 => graph is displayed but need to be redraw without animation (because of a resize); |
- // ctx.firstPass==7 => graph is displayed but need to be redraw without responsivity; |
- |
- |
- if(!dynamicFunction(data, config, ctx)) { return; } |
- |
- if(typeof ctx.firstPass == "undefined") { |
- ctx.firstPass=1; |
- var newSize=resizeGraph(ctx,config); |
- if(config.responsive) { |
- resizeCtx(ctx,newSize.newWidth,newSize.newHeight); |
- ctx.prevWidth=newSize.newWidth; |
- ctx.prevHeight=newSize.newHeight; |
- } else { |
- ctx.prevWidth=0; |
- ctx.prevHeight=0; |
- } |
- ctx.runanimationcompletefunction=true; |
- redrawGraph(ctx,data,config); |
- } else if(ctx.firstPass == 0) { |
- ctx.firstPass=1; |
- var newSize=resizeGraph(ctx,config); |
- if(config.responsive) { |
- resizeCtx(ctx,newSize.newWidth,newSize.newHeight); |
- ctx.prevWidth=newSize.newWidth; |
- ctx.prevHeight=newSize.newHeight; |
- } else { |
- ctx.prevWidth=0; |
- ctx.prevHeight=0; |
- } |
- redrawGraph(ctx,data,config); |
- } else if(ctx.firstPass==1 || ctx.firstPass==2) { |
- ctx.firstPass=2; |
- } else if (ctx.firstPass==3 || ctx.firstPass==4) { |
- ctx.firstPass=4; |
- } else if(ctx.firstPass==5) { |
- ctx.firstPass=1; |
- redrawGraph(ctx,data,config); |
- } else if(ctx.firstPass==6) { |
- var newSize=resizeGraph(ctx,config); |
- if (newSize.newWidth!=ctx.prevWidth || newSize.newHeight != ctx.prevHeight) { |
- ctx.firstPass=3; |
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
- if(config.responsive) { |
- resizeCtx(ctx,newSize.newWidth,newSize.newHeight); |
- ctx.prevWidth=newSize.newWidth; |
- ctx.prevHeight=newSize.newHeight; |
- } else { |
- ctx.prevWidth=0; |
- ctx.prevHeight=0; |
- } |
- redrawGraph(ctx,data,config); |
- } else ctx.firstPass=5; |
- } else if(ctx.firstPass==7) { |
- var newSize=resizeGraph(ctx,config); |
- ctx.firstPass=3; |
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); |
- if(config.responsive) { |
- resizeCtx(ctx,newSize.newWidth,newSize.newHeight); |
- ctx.prevWidth=newSize.newWidth; |
- ctx.prevHeight=newSize.newHeight; |
- } else { |
- ctx.prevWidth=0; |
- ctx.prevHeight=0; |
- } |
- redrawGraph(ctx,data,config); |
- } |
-}; |
- |
-function redrawGraph(ctx,data,config) { |
- var myGraph = new Chart(ctx); |
- switch (ctx.tpchart) { |
- case "Bar": |
- myGraph.Bar(data,config); |
- break; |
- case "Pie": |
- myGraph.Pie(data,config); |
- break; |
- case "Doughnut": |
- myGraph.Doughnut(data,config); |
- break; |
- case "Radar": |
- myGraph.Radar(data,config); |
- break; |
- case "PolarArea": |
- myGraph.PolarArea(data,config); |
- break; |
- case "HorizontalBar": |
- myGraph.HorizontalBar(data,config); |
- break; |
- case "StackedBar": |
- myGraph.StackedBar(data,config); |
- break; |
- case "HorizontalStackedBar": |
- myGraph.HorizontalStackedBar(data,config); |
- break; |
- case "Line": |
- myGraph.Line(data,config); |
- break; |
- } |
- |
- |
- |
-} |
- |
- |
-//Default browsercheck, added to all scripts! |
-function checkBrowser() { |
- this.ver = navigator.appVersion |
- this.dom = document.getElementById ? 1 : 0 |
- this.ie5 = (this.ver.indexOf("MSIE 5") > -1 && this.dom) ? 1 : 0; |
- this.ie4 = (document.all && !this.dom) ? 1 : 0; |
- this.ns5 = (this.dom && parseInt(this.ver) >= 5) ? 1 : 0; |
- this.ns4 = (document.layers && !this.dom) ? 1 : 0; |
- this.bw = (this.ie5 || this.ie4 || this.ns4 || this.ns5) |
- return this |
-}; |
-bw = new checkBrowser(); |
-//Set these variables: |
-fromLeft = 10; // How much from the left of the cursor should the div be? |
-fromTop = 10; // How much from the top of the cursor should the div be? |
-/******************************************************************** |
-Initilizes the objects |
-*********************************************************************/ |
-function cursorInit() { |
- scrolled = bw.ns4 || bw.ns5 ? "window.pageYOffset" : "document.body.scrollTop" |
- if (bw.ns4) document.captureEvents(Event.MOUSEMOVE) |
-}; |
-/******************************************************************** |
-Contructs the cursorobjects |
-*********************************************************************/ |
-function makeCursorObj(obj, nest) { |
- createCursorDiv(); |
- nest = (!nest) ? '' : 'document.' + nest + '.' |
- this.css = bw.dom ? document.getElementById(obj).style : bw.ie4 ? document.all[obj].style : bw.ns4 ? eval(nest + "document.layers." + obj) : 0; |
- this.moveIt = b_moveIt; |
- cursorInit(); |
- return this |
-}; |
- |
-function b_moveIt(x, y) { |
- this.x = x; |
- this.y = y; |
- this.css.left = this.x + "px"; |
- this.css.top = this.y + "px"; |
-}; |
- |
-function isIE() { |
- var myNav = navigator.userAgent.toLowerCase(); |
- return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false; |
-}; |
- |
-function mergeChartConfig(defaults, userDefined) { |
- var returnObj = {}; |
- for (var attrname in defaults) { |
- returnObj[attrname] = defaults[attrname]; |
- } |
- for (var attrname in userDefined) { |
- returnObj[attrname] = userDefined[attrname]; |
- } |
- return returnObj; |
-}; |
- |
-function sleep(ms) { |
- var dt = new Date(); |
- dt.setTime(dt.getTime() + ms); |
- while (new Date().getTime() < dt.getTime()) {}; |
-}; |
- |
-function saveCanvas(ctx, data, config) { |
- cvSave = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); |
- var saveCanvasConfig = { |
- savePng: false, |
- annotateDisplay: false, |
- animation: false, |
- dynamicDisplay: false |
- }; |
- var savePngConfig = mergeChartConfig(config, saveCanvasConfig); |
- savePngConfig.clearRect = false; |
- /* And ink them */ |
- |
- redrawGraph(ctx,data,savePngConfig); |
- if (config.savePngOutput == "NewWindow") { |
- var image = ctx.canvas.toDataURL(); |
- ctx.putImageData(cvSave, 0, 0); |
- window.open(image, '_blank'); |
- } |
- if (config.savePngOutput == "CurrentWindow") { |
- var image = ctx.canvas.toDataURL(); |
- ctx.putImageData(cvSave, 0, 0); |
- window.location.href = image; |
- } |
- if (config.savePngOutput == "Save") { |
- // document.location.href= ctx.canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); |
- // ctx.putImageData(cvSave,0,0); |
- var image = ctx.canvas.toDataURL(); |
- var downloadLink = document.createElement("a"); |
- downloadLink.href = image; |
- downloadLink.download = config.savePngName + ".png"; |
- document.body.appendChild(downloadLink); |
- downloadLink.click(); |
- document.body.removeChild(downloadLink); |
- } |
-}; |
-//if (isIE() < 9 && isIE() != false) { |
-if (typeof String.prototype.trim !== 'function') { |
- String.prototype.trim = function() { |
- return this.replace(/^\s+|\s+$/g, ''); |
- } |
-}; |
-//}; |
-var dynamicDisplay = new Array(); |
-var dynamicDisplayList = new Array(); |
- |
-function dynamicFunction(data, config, ctx) { |
- |
- if (config.dynamicDisplay) { |
- if (ctx.canvas.id == "") { |
- var cvdate = new Date(); |
- var cvmillsec = cvdate.getTime(); |
- ctx.canvas.id = "Canvas_" + cvmillsec; |
- } |
- if (typeof(dynamicDisplay[ctx.canvas.id]) == "undefined") { |
- dynamicDisplayList[dynamicDisplayList["length"]] = ctx.canvas.id; |
- dynamicDisplay[ctx.canvas.id] = [ctx, false, false, data, config, ctx.canvas]; |
- dynamicDisplay[ctx.canvas.id][1] = isScrolledIntoView(ctx.canvas); |
- window.onscroll = scrollFunction; |
- } else if (dynamicDisplay[ctx.canvas.id][2] == false) { |
- dynamicDisplay[ctx.canvas.id][1] = isScrolledIntoView(ctx.canvas); |
- } |
-// if (dynamicDisplay[ctx.canvas.id][1] == false || dynamicDisplay[ctx.canvas.id][2] == true) { |
- if (dynamicDisplay[ctx.canvas.id][1] == false && dynamicDisplay[ctx.canvas.id][2] == false) { |
- return false; |
- } |
- dynamicDisplay[ctx.canvas.id][2] = true; |
- } |
- return true; |
-}; |
- |
-function isScrolledIntoView(element) { |
- var xPosition = 0; |
- var yPosition = 0; |
- elem = element; |
- while (elem) { |
- xPosition += (elem.offsetLeft - elem.scrollLeft + elem.clientLeft); |
- yPosition += (elem.offsetTop - elem.scrollTop + elem.clientTop); |
- elem = elem.offsetParent; |
- } |
- if (xPosition + element.width / 2 >= window.pageXOffset && |
- xPosition + element.width / 2 <= window.pageXOffset + window.innerWidth && |
- yPosition + element.height / 2 >= window.pageYOffset && |
- yPosition + element.height / 2 <= window.pageYOffset + window.innerHeight |
- ) return (true); |
- else return false; |
-}; |
- |
-function scrollFunction() { |
- for (var i = 0; i < dynamicDisplayList["length"]; i++) { |
- if (isScrolledIntoView(dynamicDisplay[dynamicDisplayList[i]][5]) && dynamicDisplay[dynamicDisplayList[i]][2] == false) { |
- dynamicDisplay[dynamicDisplayList[i]][1] = true; |
- redrawGraph(dynamicDisplay[dynamicDisplayList[i]][0],dynamicDisplay[dynamicDisplayList[i]][3], dynamicDisplay[dynamicDisplayList[i]][4]); |
- } |
- } |
-}; |
- |
-var jsGraphAnnotate = new Array(); |
- |
-function clearAnnotate(ctxid) { |
- jsGraphAnnotate[ctxid] = []; |
-}; |
- |
-function getMousePos(canvas, evt) { |
- var rect = canvas.getBoundingClientRect(); |
- return { |
- x: evt.clientX - rect.left, |
- y: evt.clientY - rect.top |
- }; |
-}; |
- |
-function doMouseAction(config, ctx, event, data, action, funct) { |
- |
- var onData = false; |
- if (action == "annotate") { |
- var annotateDIV = document.getElementById('divCursor'); |
- var show = false; |
- annotateDIV.className = (config.annotateClassName) ? config.annotateClassName : ''; |
- annotateDIV.style.border = (config.annotateClassName) ? '' : config.annotateBorder; |
- annotateDIV.style.padding = (config.annotateClassName) ? '' : config.annotatePadding; |
- annotateDIV.style.borderRadius = (config.annotateClassName) ? '' : config.annotateBorderRadius; |
- annotateDIV.style.backgroundColor = (config.annotateClassName) ? '' : config.annotateBackgroundColor; |
- annotateDIV.style.color = (config.annotateClassName) ? '' : config.annotateFontColor; |
- annotateDIV.style.fontFamily = (config.annotateClassName) ? '' : config.annotateFontFamily; |
- annotateDIV.style.fontSize = (config.annotateClassName) ? '' : config.annotateFontSize + "pt"; |
- annotateDIV.style.fontStyle = (config.annotateClassName) ? '' : config.annotateFontStyle; |
- } |
- if (action=="annotate") { |
- show=false; |
- annotateDIV.style.display = show ? '' : 'none'; |
- } |
- canvas_pos = getMousePos(ctx.canvas, event); |
- for (i = 0; i < jsGraphAnnotate[ctx.ChartNewId]["length"]; i++) { |
- if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "ARC") { |
- distance = Math.sqrt((canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) * (canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) + (canvas_pos.y - jsGraphAnnotate[ctx.ChartNewId][i][2]) * (canvas_pos.y - jsGraphAnnotate[ctx.ChartNewId][i][2])); |
- if (distance > jsGraphAnnotate[ctx.ChartNewId][i][3] && distance < jsGraphAnnotate[ctx.ChartNewId][i][4]) { |
- angle = Math.acos((canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) / distance); |
- if (canvas_pos.y < jsGraphAnnotate[ctx.ChartNewId][i][2]) angle = -angle; |
- while (angle < 0) { |
- angle += 2 * Math.PI; |
- } |
- while (angle > 2 * Math.PI) { |
- angle -= 2 * Math.PI; |
- } |
- if (angle < config.startAngle * (Math.PI / 360)) angle += 2 * Math.PI; |
- if ((angle > jsGraphAnnotate[ctx.ChartNewId][i][5] && angle < jsGraphAnnotate[ctx.ChartNewId][i][6]) || (angle > jsGraphAnnotate[ctx.ChartNewId][i][5] - 2 * Math.PI && angle < jsGraphAnnotate[ctx.ChartNewId][i][6] - 2 * Math.PI) || (angle > jsGraphAnnotate[ctx.ChartNewId][i][5] + 2 * Math.PI && angle < jsGraphAnnotate[ctx.ChartNewId][i][6] + 2 * Math.PI)) { |
- v1 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][7], config.fmtV1); // V1=Label |
- v2 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][8], config.fmtV2); // V2=Data Value |
- v3 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV3); // V3=Cumulated Value |
- v4 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][10], config.fmtV4); // V4=Total Data Value |
- v5 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][11], config.fmtV5); // V5=Angle |
- v6 = fmtChartJS(config, 100 * jsGraphAnnotate[ctx.ChartNewId][i][8] / jsGraphAnnotate[ctx.ChartNewId][i][10], config.fmtV6); // v6=Percentage; |
- v6 = roundToWithThousands(config, v6, config.roundPct); |
- v7 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][1], config.fmtV7); // v7=midPointX of arc; |
- v8 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][2], config.fmtV8); // v8=midPointY of arc; |
- v9 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][3], config.fmtV9); // v9=radius Minimum; |
- v10 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][4], config.fmtV10); // v10=radius Maximum; |
- v11 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][5], config.fmtV11); // v11=start angle; |
- v12 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][6], config.fmtV12); // v12=stop angle; |
- v13 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][12], config.fmtV13); // v13=position in Data; |
- graphPosX = canvas_pos.x; |
- graphPosY = canvas_pos.y; |
- onData = true; |
- if (action == "annotate") { |
- dispString = tmplbis(config.annotateLabel, { |
- config: config, |
- v1: v1, |
- v2: v2, |
- v3: v3, |
- v4: v4, |
- v5: v5, |
- v6: v6, |
- v7: v7, |
- v8: v8, |
- v9: v9, |
- v10: v10, |
- v11: v11, |
- v12: v12, |
- v13: v13, |
- graphPosX: graphPosX, |
- graphPosY: graphPosY |
- }); |
- annotateDIV.innerHTML = dispString; |
- show = true; |
- } else { |
- funct(event, ctx, config, data, { |
- v1: v1, |
- v2: v2, |
- v3: v3, |
- v4: v4, |
- v5: v5, |
- v6: v6, |
- v7: v7, |
- v8: v8, |
- v9: v9, |
- v10: v10, |
- v11: v11, |
- v12: v12, |
- v13: v13, |
- graphPosX: graphPosX, |
- graphPosY: graphPosY |
- }); |
- } |
- if (action == "annotate") { |
- x = bw.ns4 || bw.ns5 ? event.pageX : event.x; |
- y = bw.ns4 || bw.ns5 ? event.pageY : event.y; |
- if (bw.ie4 || bw.ie5) y = y + eval(scrolled); |
- oCursor.moveIt(x + fromLeft, y + fromTop); |
- } |
- } |
- } |
- } else if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "RECT") { |
- if (canvas_pos.x > jsGraphAnnotate[ctx.ChartNewId][i][1] && canvas_pos.x < jsGraphAnnotate[ctx.ChartNewId][i][3] && canvas_pos.y < jsGraphAnnotate[ctx.ChartNewId][i][2] && canvas_pos.y > jsGraphAnnotate[ctx.ChartNewId][i][4]) { |
- v1 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][5], config.fmtV1); // V1=Label1 |
- v2 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][6], config.fmtV2); // V2=Label2 |
- v3 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][7], config.fmtV3); // V3=Data Value |
- v4 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][8], config.fmtV4); // V4=Cumulated Value |
- v5 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV5); // V5=Total Data Value |
- v6 = fmtChartJS(config, 100 * jsGraphAnnotate[ctx.ChartNewId][i][7] / jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV6); // v6=Percentage; |
- v6 = roundToWithThousands(config, v6, config.roundPct); |
- v7 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][1], config.fmtV7); // v7=top X of rectangle; |
- v8 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][2], config.fmtV8); // v8=top Y of rectangle; |
- v9 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][3], config.fmtV9); // v9=bottom X of rectangle; |
- v10 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][4], config.fmtV10); // v10=bottom Y of rectangle; |
- v11 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][10], config.fmtV11); // v11=position in Dataset; |
- v12 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][11], config.fmtV12); // v12=position in Dataset[v11].Data; |
- graphPosX = canvas_pos.x; |
- graphPosY = canvas_pos.y; |
- onData = true; |
- if (action == "annotate") { |
- dispString = tmplbis(config.annotateLabel, { |
- config: config, |
- v1: v1, |
- v2: v2, |
- v3: v3, |
- v4: v4, |
- v5: v5, |
- v6: v6, |
- v7: v7, |
- v8: v8, |
- v9: v9, |
- v10: v10, |
- v11: v11, |
- v12: v12, |
- graphPosX: graphPosX, |
- graphPosY: graphPosY, |
- data: data |
- }); |
- annotateDIV.innerHTML = dispString; |
- show = true; |
- } else { |
- funct(event, ctx, config, data, { |
- v1: v1, |
- v2: v2, |
- v3: v3, |
- v4: v4, |
- v5: v5, |
- v6: v6, |
- v7: v7, |
- v8: v8, |
- v9: v9, |
- v10: v10, |
- v11: v11, |
- v12: v12, |
- graphPosX: graphPosX, |
- graphPosY: graphPosY |
- }); |
- } |
- if (action == "annotate") { |
- x = bw.ns4 || bw.ns5 ? event.pageX : event.x; |
- y = bw.ns4 || bw.ns5 ? event.pageY : event.y; |
- if (bw.ie4 || bw.ie5) y = y + eval(scrolled); |
- oCursor.moveIt(x + fromLeft, y + fromTop); |
- } |
- } |
- } else if (jsGraphAnnotate[ctx.ChartNewId][i][0] == "POINT") { |
- distance = Math.sqrt((canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) * (canvas_pos.x - jsGraphAnnotate[ctx.ChartNewId][i][1]) + (canvas_pos.y - jsGraphAnnotate[ctx.ChartNewId][i][2]) * (canvas_pos.y - jsGraphAnnotate[ctx.ChartNewId][i][2])); |
- if (distance < 10) { |
- v1 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][3], config.fmtV1); // V1=Label1 |
- v2 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][4], config.fmtV2); // V2=Label2 |
- v3 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][5], config.fmtV3); // V3=Data Value |
- v4 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][6], config.fmtV4); // V4=Difference with Previous line |
- v5 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][7], config.fmtV5); // V5=Difference with next line; |
- v6 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][8], config.fmtV6); // V6=max; |
- v7 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV7); // V7=Total; |
- v8 = fmtChartJS(config, 100 * jsGraphAnnotate[ctx.ChartNewId][i][5] / jsGraphAnnotate[ctx.ChartNewId][i][9], config.fmtV8); // v8=percentage; |
- v8 = roundToWithThousands(config, v8, config.roundPct); |
- v9 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][1], config.fmtV9); // v9=pos X of point; |
- v10 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][2], config.fmtV10); // v10=pos Y of point; |
- v11 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][10], config.fmtV11); // v11=position in Dataset; |
- v12 = fmtChartJS(config, jsGraphAnnotate[ctx.ChartNewId][i][11], config.fmtV12); // v12=position in Dataset[v11].Data; |
- graphPosX = canvas_pos.x; |
- graphPosY = canvas_pos.y; |
- onData = true; |
- if (action == "annotate") { |
- dispString = tmplbis(config.annotateLabel, { |
- config: config, |
- v1: v1, |
- v2: v2, |
- v3: v3, |
- v4: v4, |
- v5: v5, |
- v6: v6, |
- v7: v7, |
- v8: v8, |
- v9: v9, |
- v10: v10, |
- v11: v11, |
- v12: v12, |
- graphPosX: graphPosX, |
- graphPosY: graphPosY, |
- data: data |
- }); |
- annotateDIV.innerHTML = dispString; |
- show = true; |
- } else { |
- funct(event, ctx, config, data, { |
- v1: v1, |
- v2: v2, |
- v3: v3, |
- v4: v4, |
- v5: v5, |
- v6: v6, |
- v7: v7, |
- v8: v8, |
- v9: v9, |
- v10: v10, |
- v11: v11, |
- v12: v12, |
- graphPosX: graphPosX, |
- graphPosY: graphPosY |
- }); |
- } |
- if (action == "annotate") { |
- x = bw.ns4 || bw.ns5 ? event.pageX : event.x; |
- y = bw.ns4 || bw.ns5 ? event.pageY : event.y; |
- if (bw.ie4 || bw.ie5) y = y + eval(scrolled); |
- oCursor.moveIt(x + fromLeft, y + fromTop); |
- } |
- } |
- } |
- if (action == "annotate") { |
- annotateDIV.style.display = show ? '' : 'none'; |
- } |
- } |
- if (onData == false && action != "annotate") { |
- funct(event, ctx, config, data, null); |
- } |
-}; |
-///////// GRAPHICAL PART OF THE SCRIPT /////////////////////////////////////////// |
-//Define the global Chart Variable as a class. |
-window.Chart = function(context) { |
- var chart = this; |
- //Easing functions adapted from Robert Penner's easing equations |
- //http://www.robertpenner.com/easing/ |
- var animationOptions = { |
- linear: function(t) { |
- return t; |
- }, |
- easeInQuad: function(t) { |
- return t * t; |
- }, |
- easeOutQuad: function(t) { |
- return -1 * t * (t - 2); |
- }, |
- easeInOutQuad: function(t) { |
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t; |
- return -1 / 2 * ((--t) * (t - 2) - 1); |
- }, |
- easeInCubic: function(t) { |
- return t * t * t; |
- }, |
- easeOutCubic: function(t) { |
- return 1 * ((t = t / 1 - 1) * t * t + 1); |
- }, |
- easeInOutCubic: function(t) { |
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t; |
- return 1 / 2 * ((t -= 2) * t * t + 2); |
- }, |
- easeInQuart: function(t) { |
- return t * t * t * t; |
- }, |
- easeOutQuart: function(t) { |
- return -1 * ((t = t / 1 - 1) * t * t * t - 1); |
- }, |
- easeInOutQuart: function(t) { |
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t; |
- return -1 / 2 * ((t -= 2) * t * t * t - 2); |
- }, |
- easeInQuint: function(t) { |
- return 1 * (t /= 1) * t * t * t * t; |
- }, |
- easeOutQuint: function(t) { |
- return 1 * ((t = t / 1 - 1) * t * t * t * t + 1); |
- }, |
- easeInOutQuint: function(t) { |
- if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t; |
- return 1 / 2 * ((t -= 2) * t * t * t * t + 2); |
- }, |
- easeInSine: function(t) { |
- return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1; |
- }, |
- easeOutSine: function(t) { |
- return 1 * Math.sin(t / 1 * (Math.PI / 2)); |
- }, |
- easeInOutSine: function(t) { |
- return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1); |
- }, |
- easeInExpo: function(t) { |
- return (t == 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1)); |
- }, |
- easeOutExpo: function(t) { |
- return (t == 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1); |
- }, |
- easeInOutExpo: function(t) { |
- if (t == 0) return 0; |
- if (t == 1) return 1; |
- if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1)); |
- return 1 / 2 * (-Math.pow(2, -10 * --t) + 2); |
- }, |
- easeInCirc: function(t) { |
- if (t >= 1) return t; |
- return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1); |
- }, |
- easeOutCirc: function(t) { |
- return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t); |
- }, |
- easeInOutCirc: function(t) { |
- if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1); |
- return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1); |
- }, |
- easeInElastic: function(t) { |
- var s = 1.70158; |
- var p = 0; |
- var a = 1; |
- if (t == 0) return 0; |
- if ((t /= 1) == 1) return 1; |
- if (!p) p = 1 * .3; |
- if (a < Math.abs(1)) { |
- a = 1; |
- var s = p / 4; |
- } else var s = p / (2 * Math.PI) * Math.asin(1 / a); |
- return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); |
- }, |
- easeOutElastic: function(t) { |
- var s = 1.70158; |
- var p = 0; |
- var a = 1; |
- if (t == 0) return 0; |
- if ((t /= 1) == 1) return 1; |
- if (!p) p = 1 * .3; |
- if (a < Math.abs(1)) { |
- a = 1; |
- var s = p / 4; |
- } else var s = p / (2 * Math.PI) * Math.asin(1 / a); |
- return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1; |
- }, |
- easeInOutElastic: function(t) { |
- var s = 1.70158; |
- var p = 0; |
- var a = 1; |
- if (t == 0) return 0; |
- if ((t /= 1 / 2) == 2) return 1; |
- if (!p) p = 1 * (.3 * 1.5); |
- if (a < Math.abs(1)) { |
- a = 1; |
- var s = p / 4; |
- } else var s = p / (2 * Math.PI) * Math.asin(1 / a); |
- if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); |
- return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * .5 + 1; |
- }, |
- easeInBack: function(t) { |
- var s = 1.70158; |
- return 1 * (t /= 1) * t * ((s + 1) * t - s); |
- }, |
- easeOutBack: function(t) { |
- var s = 1.70158; |
- return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1); |
- }, |
- easeInOutBack: function(t) { |
- var s = 1.70158; |
- if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)); |
- return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); |
- }, |
- easeInBounce: function(t) { |
- return 1 - animationOptions.easeOutBounce(1 - t); |
- }, |
- easeOutBounce: function(t) { |
- if ((t /= 1) < (1 / 2.75)) { |
- return 1 * (7.5625 * t * t); |
- } else if (t < (2 / 2.75)) { |
- return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + .75); |
- } else if (t < (2.5 / 2.75)) { |
- return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375); |
- } else { |
- return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375); |
- } |
- }, |
- easeInOutBounce: function(t) { |
- if (t < 1 / 2) return animationOptions.easeInBounce(t * 2) * .5; |
- return animationOptions.easeOutBounce(t * 2 - 1) * .5 + 1 * .5; |
- } |
- }; |
- //Variables global to the chart |
- var width = context.canvas.width; |
- var height = context.canvas.height; |
- //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale. |
- if (window.devicePixelRatio) { |
- context.canvas.style.width = width + "px"; |
- context.canvas.style.height = height + "px"; |
- context.canvas.height = height * window.devicePixelRatio; |
- context.canvas.width = width * window.devicePixelRatio; |
- context.scale(window.devicePixelRatio, window.devicePixelRatio); |
- }; |
- this.PolarArea = function(data, options) { |
- chart.PolarArea.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingRadius: 5, |
- inGraphDataPaddingAngle: 0, |
- inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>", |
- inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center" |
- inGraphDataVAlign: "off-center", // "bottom", "center", "top", "off-center" or "to-center" |
- inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels" |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- inGraphDataRadiusPosition: 3, |
- inGraphDataAnglePosition: 2, |
- scaleOverlay: true, |
- scaleOverride: false, |
- scaleOverride2: false, |
- scaleSteps: null, |
- scaleStepWidth: null, |
- scaleStartValue: null, |
- scaleShowLine: true, |
- scaleLineColor: "rgba(0,0,0,.1)", |
- scaleLineWidth: 1, |
- scaleShowLabels: true, |
- scaleShowLabels2: true, |
- scaleLabel: "<%=value%>", |
- scaleFontFamily: "'Arial'", |
- scaleFontSize: 12, |
- scaleFontStyle: "normal", |
- scaleFontColor: "#666", |
- scaleShowLabelBackdrop: true, |
- scaleBackdropColor: "rgba(255,255,255,0.75)", |
- scaleBackdropPaddingY: 2, |
- scaleBackdropPaddingX: 2, |
- segmentShowStroke: true, |
- segmentStrokeColor: "#fff", |
- segmentStrokeWidth: 2, |
- animation: true, |
- animationSteps: 100, |
- animationEasing: "easeOutBounce", |
- animateRotate: true, |
- animateScale: false, |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>", |
- startAngle: 90 |
- }; |
- chart.PolarArea.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.PolarArea.defaults); |
- chart.PolarArea.defaults = mergeChartConfig(chart.PolarArea.defaults, charJSPersonalDefaultOptions); |
- chart.PolarArea.defaults = mergeChartConfig(chart.PolarArea.defaults, charJSPersonalDefaultOptionsPolarArea); |
- var config = (options) ? mergeChartConfig(chart.PolarArea.defaults, options) : chart.PolarArea.defaults; |
- return new PolarArea(data, config, context); |
- }; |
- this.Radar = function(data, options) { |
- chart.Radar.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingRadius: 5, |
- inGraphDataTmpl: "<%=v3%>", |
- inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center" |
- inGraphDataVAlign: "off-center", // "right", "center", "left", "off-center" or "to-center" |
- inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels" |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- inGraphDataRadiusPosition: 3, |
- yAxisMinimumInterval: "none", |
- scaleOverlay: false, |
- scaleOverride: false, |
- scaleOverride2: false, |
- scaleSteps: null, |
- scaleStepWidth: null, |
- scaleStartValue: null, |
- scaleShowLine: true, |
- scaleLineColor: "rgba(0,0,0,.1)", |
- scaleLineWidth: 1, |
- scaleShowLabels: false, |
- scaleShowLabels2: true, |
- scaleLabel: "<%=value%>", |
- scaleFontFamily: "'Arial'", |
- scaleFontSize: 12, |
- scaleFontStyle: "normal", |
- scaleFontColor: "#666", |
- scaleShowLabelBackdrop: true, |
- scaleBackdropColor: "rgba(255,255,255,0.75)", |
- scaleBackdropPaddingY: 2, |
- scaleBackdropPaddingX: 2, |
- angleShowLineOut: true, |
- angleLineColor: "rgba(0,0,0,.1)", |
- angleLineWidth: 1, |
- pointLabelFontFamily: "'Arial'", |
- pointLabelFontStyle: "normal", |
- pointLabelFontSize: 12, |
- pointLabelFontColor: "#666", |
- pointDot: true, |
- pointDotRadius: 3, |
- pointDotStrokeWidth: 1, |
- datasetFill: true, |
- datasetStrokeWidth: 2, |
- animation: true, |
- animationSteps: 60, |
- animationEasing: "easeOutQuart", |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3%>", |
- startAngle: 90, |
- graphMaximized: false // if true, the graph will not be centered in the middle of the canvas |
- }; |
- // merge annotate defaults |
- chart.Radar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Radar.defaults); |
- chart.Radar.defaults = mergeChartConfig(chart.Radar.defaults, charJSPersonalDefaultOptions); |
- chart.Radar.defaults = mergeChartConfig(chart.Radar.defaults, charJSPersonalDefaultOptionsRadar); |
- var config = (options) ? mergeChartConfig(chart.Radar.defaults, options) : chart.Radar.defaults; |
- return new Radar(data, config, context); |
- }; |
- this.Pie = function(data, options) { |
- chart.Pie.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingRadius: 5, |
- inGraphDataPaddingAngle: 0, |
- inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>", |
- inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center" |
- inGraphDataVAlign: "off-center", // "bottom", "center", "top", "off-center" or "to-center" |
- inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels" |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- inGraphDataRadiusPosition: 3, |
- inGraphDataAnglePosition: 2, |
- inGraphDataMinimumAngle : 0, |
- segmentShowStroke: true, |
- segmentStrokeColor: "#fff", |
- segmentStrokeWidth: 2, |
- animation: true, |
- animationSteps: 100, |
- animationEasing: "easeOutBounce", |
- animateRotate: true, |
- animateScale: false, |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>", |
- startAngle: 90, |
- radiusScale: 1 |
- }; |
- // merge annotate defaults |
- chart.Pie.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Pie.defaults); |
- chart.Pie.defaults = mergeChartConfig(chart.Pie.defaults, charJSPersonalDefaultOptions); |
- chart.Pie.defaults = mergeChartConfig(chart.Pie.defaults, charJSPersonalDefaultOptionsPie); |
- var config = (options) ? mergeChartConfig(chart.Pie.defaults, options) : chart.Pie.defaults; |
- return new Pie(data, config, context); |
- }; |
- this.Doughnut = function(data, options) { |
- chart.Doughnut.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingRadius: 5, |
- inGraphDataPaddingAngle: 0, |
- inGraphDataTmpl: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>", |
- inGraphDataAlign: "off-center", // "right", "center", "left", "off-center" or "to-center" |
- inGraphDataVAlign: "off-center", // "bottom", "middle", "top", "off-center" or "to-center" |
- inGraphDataRotate: 0, // rotateAngle value (0->360) , "inRadiusAxis" or "inRadiusAxisRotateLabels" |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- inGraphDataRadiusPosition: 3, |
- inGraphDataAnglePosition: 2, |
- inGraphDataMinimumAngle : 0, |
- segmentShowStroke: true, |
- segmentStrokeColor: "#fff", |
- segmentStrokeWidth: 2, |
- percentageInnerCutout: 50, |
- animation: true, |
- animationSteps: 100, |
- animationEasing: "easeOutBounce", |
- animateRotate: true, |
- animateScale: false, |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == ''? '' : v1+':')+ v2 + ' (' + v6 + ' %)'%>", |
- startAngle: 90, |
- radiusScale: 1 |
- }; |
- // merge annotate defaults |
- chart.Doughnut.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Doughnut.defaults); |
- chart.Doughnut.defaults = mergeChartConfig(chart.Doughnut.defaults, charJSPersonalDefaultOptions); |
- chart.Doughnut.defaults = mergeChartConfig(chart.Doughnut.defaults, charJSPersonalDefaultOptionsDoughnut); |
- var config = (options) ? mergeChartConfig(chart.Doughnut.defaults, options) : chart.Doughnut.defaults; |
- return new Doughnut(data, config, context); |
- }; |
- this.Line = function(data, options) { |
- chart.Line.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingX: 3, |
- inGraphDataPaddingY: 3, |
- inGraphDataTmpl: "<%=v3%>", |
- inGraphDataAlign: "left", |
- inGraphDataVAlign: "bottom", |
- inGraphDataRotate: 0, |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- drawXScaleLine: [{ |
- position: "bottom" |
- }], |
- scaleOverlay: false, |
- scaleOverride: false, |
- scaleOverride2: false, |
- scaleSteps: null, |
- scaleStepWidth: null, |
- scaleStartValue: null, |
- scaleSteps2: null, |
- scaleStepWidth2: null, |
- scaleStartValue2: null, |
- scaleLabel2 : "<%=value%>", |
- scaleLineColor: "rgba(0,0,0,.1)", |
- scaleLineWidth: 1, |
- scaleShowLabels: true, |
- scaleShowLabels2: true, |
- scaleLabel: "<%=value%>", |
- scaleFontFamily: "'Arial'", |
- scaleFontSize: 12, |
- scaleFontStyle: "normal", |
- scaleFontColor: "#666", |
- scaleShowGridLines: true, |
- scaleXGridLinesStep: 1, |
- scaleYGridLinesStep: 1, |
- scaleGridLineColor: "rgba(0,0,0,.05)", |
- scaleGridLineWidth: 1, |
- showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels) |
- rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; |
- // you can force an integer value between 0 and 180 degres |
- logarithmic: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale |
- logarithmic2: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale |
- scaleTickSizeLeft: 5, |
- scaleTickSizeRight: 5, |
- scaleTickSizeBottom: 5, |
- scaleTickSizeTop: 5, |
- bezierCurve: true, |
- pointDot: true, |
- pointDotRadius: 4, |
- pointDotStrokeWidth: 2, |
- datasetStrokeWidth: 2, |
- datasetFill: true, |
- animation: true, |
- animationSteps: 60, |
- animationEasing: "easeOutQuart", |
- extrapolateMissingData: true, |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3%>" |
- }; |
- // merge annotate defaults |
- chart.Line.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Line.defaults); |
- chart.Line.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.Line.defaults); |
- chart.Line.defaults = mergeChartConfig(chart.Line.defaults, charJSPersonalDefaultOptions); |
- chart.Line.defaults = mergeChartConfig(chart.Line.defaults, charJSPersonalDefaultOptionsLine); |
- var config = (options) ? mergeChartConfig(chart.Line.defaults, options) : chart.Line.defaults; |
- return new Line(data, config, context); |
- }; |
- this.StackedBar = function(data, options) { |
- chart.StackedBar.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingX: 0, |
- inGraphDataPaddingY: -3, |
- inGraphDataTmpl: "<%=v3%>", |
- inGraphDataAlign: "center", |
- inGraphDataVAlign: "top", |
- inGraphDataRotate: 0, |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- inGraphDataXPosition: 2, |
- inGraphDataYPosition: 3, |
- scaleOverlay: false, |
- scaleOverride: false, |
- scaleOverride2: false, |
- scaleSteps: null, |
- scaleStepWidth: null, |
- scaleStartValue: null, |
- scaleLineColor: "rgba(0,0,0,.1)", |
- scaleLineWidth: 1, |
- scaleShowLabels: true, |
- scaleShowLabels2: true, |
- scaleLabel: "<%=value%>", |
- scaleFontFamily: "'Arial'", |
- scaleFontSize: 12, |
- scaleFontStyle: "normal", |
- scaleFontColor: "#666", |
- scaleShowGridLines: true, |
- scaleXGridLinesStep: 1, |
- scaleYGridLinesStep: 1, |
- scaleGridLineColor: "rgba(0,0,0,.05)", |
- scaleGridLineWidth: 1, |
- showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels) |
- rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; |
- // you can force an integer value between 0 and 180 degres |
- scaleTickSizeLeft: 5, |
- scaleTickSizeRight: 5, |
- scaleTickSizeBottom: 5, |
- scaleTickSizeTop: 5, |
- barShowStroke: true, |
- barStrokeWidth: 2, |
- barValueSpacing: 5, |
- barDatasetSpacing: 1, |
- animation: true, |
- animationSteps: 60, |
- animationEasing: "easeOutQuart", |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>" |
- }; |
- // merge annotate defaults |
- chart.StackedBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.StackedBar.defaults); |
- chart.StackedBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.StackedBar.defaults); |
- chart.StackedBar.defaults = mergeChartConfig(chart.StackedBar.defaults, charJSPersonalDefaultOptions); |
- chart.StackedBar.defaults = mergeChartConfig(chart.StackedBar.defaults, charJSPersonalDefaultOptionsStackedBar); |
- var config = (options) ? mergeChartConfig(chart.StackedBar.defaults, options) : chart.StackedBar.defaults; |
- return new StackedBar(data, config, context); |
- }; |
- this.HorizontalStackedBar = function(data, options) { |
- chart.HorizontalStackedBar.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingX: -3, |
- inGraphDataPaddingY: 0, |
- inGraphDataTmpl: "<%=v3%>", |
- inGraphDataAlign: "right", |
- inGraphDataVAlign: "middle", |
- inGraphDataRotate: 0, |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- inGraphDataXPosition: 3, |
- inGraphDataYPosition: 2, |
- scaleOverlay: false, |
- scaleOverride: false, |
- scaleOverride2: false, |
- scaleSteps: null, |
- scaleStepWidth: null, |
- scaleStartValue: null, |
- scaleLineColor: "rgba(0,0,0,.1)", |
- scaleLineWidth: 1, |
- scaleShowLabels: true, |
- scaleShowLabels2: true, |
- scaleLabel: "<%=value%>", |
- scaleFontFamily: "'Arial'", |
- scaleFontSize: 12, |
- scaleFontStyle: "normal", |
- scaleFontColor: "#666", |
- scaleShowGridLines: true, |
- scaleXGridLinesStep: 1, |
- scaleYGridLinesStep: 1, |
- scaleGridLineColor: "rgba(0,0,0,.05)", |
- scaleGridLineWidth: 1, |
- scaleTickSizeLeft: 5, |
- scaleTickSizeRight: 5, |
- scaleTickSizeBottom: 5, |
- scaleTickSizeTop: 5, |
- showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels) |
- rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; |
- barShowStroke: true, |
- barStrokeWidth: 2, |
- barValueSpacing: 5, |
- barDatasetSpacing: 1, |
- animation: true, |
- animationSteps: 60, |
- animationEasing: "easeOutQuart", |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>", |
- reverseOrder: false |
- }; |
- // merge annotate defaults |
- chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.HorizontalStackedBar.defaults); |
- chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.HorizontalStackedBar.defaults); |
- chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.HorizontalStackedBar.defaults, charJSPersonalDefaultOptions); |
- chart.HorizontalStackedBar.defaults = mergeChartConfig(chart.HorizontalStackedBar.defaults, charJSPersonalDefaultOptionsHorizontalStackedBar); |
- var config = (options) ? mergeChartConfig(chart.HorizontalStackedBar.defaults, options) : chart.HorizontalStackedBar.defaults; |
- return new HorizontalStackedBar(data, config, context); |
- }; |
- this.Bar = function(data, options) { |
- chart.Bar.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingX: 0, |
- inGraphDataPaddingY: 3, |
- inGraphDataTmpl: "<%=v3%>", |
- inGraphDataAlign: "center", |
- inGraphDataVAlign: "bottom", |
- inGraphDataRotate: 0, |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- inGraphDataXPosition: 2, |
- inGraphDataYPosition: 3, |
- scaleOverlay: false, |
- scaleOverride: false, |
- scaleOverride2: false, |
- scaleSteps: null, |
- scaleStepWidth: null, |
- scaleStartValue: null, |
- scaleLineColor: "rgba(0,0,0,.1)", |
- scaleLineWidth: 1, |
- scaleShowLabels: true, |
- scaleShowLabels2: true, |
- scaleLabel: "<%=value%>", |
- scaleFontFamily: "'Arial'", |
- scaleFontSize: 12, |
- scaleFontStyle: "normal", |
- scaleFontColor: "#666", |
- scaleShowGridLines: true, |
- scaleXGridLinesStep: 1, |
- scaleYGridLinesStep: 1, |
- scaleGridLineColor: "rgba(0,0,0,.05)", |
- scaleGridLineWidth: 1, |
- showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels) |
- rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; |
- // you can force an integer value between 0 and 180 degres |
- logarithmic: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale |
- logarithmic2: false, // can be 'fuzzy',true and false ('fuzzy' => if the gap between min and maximum is big it's using a logarithmic y-Axis scale |
- scaleTickSizeLeft: 5, |
- scaleTickSizeRight: 5, |
- scaleTickSizeBottom: 5, |
- scaleTickSizeTop: 5, |
- barShowStroke: true, |
- barStrokeWidth: 2, |
- barValueSpacing: 5, |
- barDatasetSpacing: 1, |
- barBorderRadius: 0, |
- animation: true, |
- animationSteps: 60, |
- animationEasing: "easeOutQuart", |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>" |
- }; |
- // merge annotate defaults |
- chart.Bar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.Bar.defaults); |
- chart.Bar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.Bar.defaults); |
- chart.Bar.defaults = mergeChartConfig(chart.Bar.defaults, charJSPersonalDefaultOptions); |
- chart.Bar.defaults = mergeChartConfig(chart.Bar.defaults, charJSPersonalDefaultOptionsBar); |
- var config = (options) ? mergeChartConfig(chart.Bar.defaults, options) : chart.Bar.defaults; |
- return new Bar(data, config, context); |
- }; |
- this.HorizontalBar = function(data, options) { |
- chart.HorizontalBar.defaults = { |
- inGraphDataShow: false, |
- inGraphDataPaddingX: 3, |
- inGraphDataPaddingY: 0, |
- inGraphDataTmpl: "<%=v3%>", |
- inGraphDataAlign: "left", |
- inGraphDataVAlign: "middle", |
- inGraphDataRotate: 0, |
- inGraphDataFontFamily: "'Arial'", |
- inGraphDataFontSize: 12, |
- inGraphDataFontStyle: "normal", |
- inGraphDataFontColor: "#666", |
- inGraphDataXPosition: 3, |
- inGraphDataYPosition: 2, |
- scaleOverlay: false, |
- scaleOverride: false, |
- scaleOverride2: false, |
- scaleSteps: null, |
- scaleStepWidth: null, |
- scaleStartValue: null, |
- scaleLineColor: "rgba(0,0,0,.1)", |
- scaleLineWidth: 1, |
- scaleShowLabels: true, |
- scaleShowLabels2: true, |
- scaleLabel: "<%=value%>", |
- scaleFontFamily: "'Arial'", |
- scaleFontSize: 12, |
- scaleFontStyle: "normal", |
- scaleFontColor: "#666", |
- scaleShowGridLines: true, |
- scaleXGridLinesStep: 1, |
- scaleYGridLinesStep: 1, |
- scaleGridLineColor: "rgba(0,0,0,.05)", |
- scaleGridLineWidth: 1, |
- scaleTickSizeLeft: 5, |
- scaleTickSizeRight: 5, |
- scaleTickSizeBottom: 5, |
- scaleTickSizeTop: 5, |
- showYAxisMin: true, // Show the minimum value on Y axis (in original version, this minimum is not displayed - it can overlap the X labels) |
- rotateLabels: "smart", // smart <=> 0 degre if space enough; otherwise 45 degres if space enough otherwise90 degre; |
- barShowStroke: true, |
- barStrokeWidth: 2, |
- barValueSpacing: 5, |
- barDatasetSpacing: 1, |
- barBorderRadius: 0, |
- animation: true, |
- animationSteps: 60, |
- animationEasing: "easeOutQuart", |
- onAnimationComplete: null, |
- annotateLabel: "<%=(v1 == '' ? '' : v1) + (v1!='' && v2 !='' ? ' - ' : '')+(v2 == '' ? '' : v2)+(v1!='' || v2 !='' ? ':' : '') + v3 + ' (' + v6 + ' %)'%>", |
- reverseOrder: false |
- }; |
- // merge annotate defaults |
- chart.HorizontalBar.defaults = mergeChartConfig(chart.defaults.commonOptions, chart.HorizontalBar.defaults); |
- chart.HorizontalBar.defaults = mergeChartConfig(chart.defaults.xyAxisCommonOptions, chart.HorizontalBar.defaults); |
- chart.HorizontalBar.defaults = mergeChartConfig(chart.HorizontalBar.defaults, charJSPersonalDefaultOptions); |
- chart.HorizontalBar.defaults = mergeChartConfig(chart.HorizontalBar.defaults, charJSPersonalDefaultOptionsHorizontalBar); |
- var config = (options) ? mergeChartConfig(chart.HorizontalBar.defaults, options) : chart.HorizontalBar.defaults; |
- return new HorizontalBar(data, config, context); |
- }; |
- chart.defaults = {}; |
- chart.defaults.commonOptions = { |
- multiGraph: false, |
- clearRect: true, // do not change clearRect options; for internal use only |
- dynamicDisplay: false, |
- graphSpaceBefore: 5, |
- graphSpaceAfter: 5, |
- canvasBorders: false, |
- canvasBackgroundColor: "none", |
- canvasBordersWidth: 3, |
- canvasBordersColor: "black", |
- graphTitle: "", |
- graphTitleFontFamily: "'Arial'", |
- graphTitleFontSize: 24, |
- graphTitleFontStyle: "bold", |
- graphTitleFontColor: "#666", |
- graphTitleSpaceBefore: 5, |
- graphTitleSpaceAfter: 5, |
- graphSubTitle: "", |
- graphSubTitleFontFamily: "'Arial'", |
- graphSubTitleFontSize: 18, |
- graphSubTitleFontStyle: "normal", |
- graphSubTitleFontColor: "#666", |
- graphSubTitleSpaceBefore: 5, |
- graphSubTitleSpaceAfter: 5, |
- footNote: "", |
- footNoteFontFamily: "'Arial'", |
- footNoteFontSize: 8, |
- footNoteFontStyle: "bold", |
- footNoteFontColor: "#666", |
- footNoteSpaceBefore: 5, |
- footNoteSpaceAfter: 5, |
- legend : false, |
- showSingleLegend: false, |
- maxLegendCols : 999, |
- legendPosY :4, |
- legendPosX : -2, |
- legendFontFamily: "'Arial'", |
- legendFontSize: 12, |
- legendFontStyle: "normal", |
- legendFontColor: "#666", |
- legendBlockSize: 15, |
- legendBorders: true, |
- legendBordersWidth: 1, |
- legendBordersColors: "#666", |
- legendBordersSpaceBefore: 5, |
- legendBordersSpaceAfter: 5, |
- legendBordersSpaceLeft: 5, |
- legendBordersSpaceRight: 5, |
- legendSpaceBeforeText: 5, |
- legendSpaceAfterText: 5, |
- legendSpaceLeftText: 5, |
- legendSpaceRightText: 5, |
- legendSpaceBetweenTextVertical: 5, |
- legendSpaceBetweenTextHorizontal: 5, |
- legendSpaceBetweenBoxAndText: 5, |
- legendFillColor : "rgba(0,0,0,0)", |
- legendXPadding : 0, |
- legendYPadding : 0, |
- annotateDisplay: false, |
- savePng: false, |
- savePngOutput: "NewWindow", // Allowed values : "NewWindow", "CurrentWindow", "Save" |
- savePngFunction: "mousedown right", |
- savePngBackgroundColor: 'WHITE', |
- annotateFunction: "mousemove", |
- annotateFontFamily: "'Arial'", |
- annotateBorder: 'none', |
- annotateBorderRadius: '2px', |
- annotateBackgroundColor: 'rgba(0,0,0,0.8)', |
- annotateFontSize: 12, |
- annotateFontColor: 'white', |
- annotateFontStyle: "normal", |
- annotatePadding: "3px", |
- annotateClassName: "", |
- crossText: [""], |
- crossTextIter: ["all"], |
- crossTextOverlay: [true], |
- crossTextFontFamily: ["'Arial'"], |
- crossTextFontSize: [12], |
- crossTextFontStyle: ["normal"], |
- crossTextFontColor: ["rgba(220,220,220,1)"], |
- crossTextRelativePosX: [2], |
- crossTextRelativePosY: [2], |
- crossTextBaseline: ["middle"], |
- crossTextAlign: ["center"], |
- crossTextPosX: [0], |
- crossTextPosY: [0], |
- crossTextAngle: [0], |
- crossTextFunction: null, |
- crossImage: [undefined], |
- crossImageIter: ["all"], |
- crossImageOverlay: [true], |
- crossImageRelativePosX: [2], |
- crossImageRelativePosY: [2], |
- crossImageBaseline: ["middle"], |
- crossImageAlign: ["center"], |
- crossImagePosX: [0], |
- crossImagePosY: [0], |
- crossImageAngle: [0], |
- spaceTop: 0, |
- spaceBottom: 0, |
- spaceRight: 0, |
- spaceLeft: 0, |
- decimalSeparator: ".", |
- thousandSeparator: "", |
- roundNumber: "none", |
- roundPct: -1, |
- fmtV1: "none", |
- fmtV2: "none", |
- fmtV3: "none", |
- fmtV4: "none", |
- fmtV5: "none", |
- fmtV6: "none", |
- fmtV7: "none", |
- fmtV8: "none", |
- fmtV9: "none", |
- fmtV10: "none", |
- fmtV11: "none", |
- fmtV12: "none", |
- fmtV13: "none", |
- fmtXLabel: "none", |
- fmtYLabel: "none", |
- fmtYLabel2: "none", |
- fmtLegend: "none", |
- animationStartValue: 0, |
- animationStopValue: 1, |
- animationCount: 1, |
- animationPauseTime: 5, |
- animationBackward: false, |
- animationStartWithDataset: 1, |
- animationStartWithData: 1, |
- animationLeftToRight: false, |
- animationByDataset: false, |
- defaultStrokeColor: "rgba(220,220,220,1)", |
- defaultFillColor: "rgba(220,220,220,0.5)", |
- mouseDownRight: null, |
- mouseDownLeft: null, |
- mouseDownMiddle: null, |
- mouseMove: null, |
- mouseOut: null, |
- mouseWheel : null, |
- savePngName: "canvas", |
- responsive : false, |
- maintainAspectRatio: true |
- }; |
- chart.defaults.xyAxisCommonOptions = { |
- yAxisMinimumInterval: "none", |
- yAxisMinimumInterval2: "none", |
- yScaleLabelsMinimumWidth: 0, |
- xScaleLabelsMinimumWidth: 0, |
- yAxisLeft: true, |
- yAxisRight: false, |
- xAxisBottom: true, |
- xAxisTop: false, |
- xAxisSpaceBetweenLabels: 5, |
- fullWidthGraph: false, |
- yAxisLabel: "", |
- yAxisLabel2: "", |
- yAxisFontFamily: "'Arial'", |
- yAxisFontSize: 16, |
- yAxisFontStyle: "normal", |
- yAxisFontColor: "#666", |
- yAxisLabelSpaceRight: 5, |
- yAxisLabelSpaceLeft: 5, |
- yAxisSpaceRight: 5, |
- yAxisSpaceLeft: 5, |
- xAxisLabel: "", |
- xAxisFontFamily: "'Arial'", |
- xAxisFontSize: 16, |
- xAxisFontStyle: "normal", |
- xAxisFontColor: "#666", |
- xAxisLabelSpaceBefore: 5, |
- xAxisLabelSpaceAfter: 5, |
- xAxisSpaceBefore: 5, |
- xAxisSpaceAfter: 5, |
- yAxisUnit: "", |
- yAxisUnit2: "", |
- yAxisUnitFontFamily: "'Arial'", |
- yAxisUnitFontSize: 8, |
- yAxisUnitFontStyle: "normal", |
- yAxisUnitFontColor: "#666", |
- yAxisUnitSpaceBefore: 5, |
- yAxisUnitSpaceAfter: 5 |
- }; |
- var clear = function(c) { |
- c.clearRect(0, 0, width, height); |
- }; |
- |
- function setting_new_chart_vars(ctx) { |
- |
- if (typeof ctx.ChartNewId === typeof undefined) { |
- ctx.runanimationcompletefunction=true; |
- var cvdate = new Date(); |
- var cvmillsec = cvdate.getTime(); |
- ctx.ChartNewId = ctx.tpchart + '_' + cvmillsec; |
- ctx._eventListeners = {}; |
- } |
- } |
- |
- var PolarArea = function(data, config, ctx) { |
- var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, msr, midPosX, midPosY; |
- |
- ctx.tpchart="PolarArea"; |
- setting_new_chart_vars(ctx); |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- var realStartAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI; |
- while (config.startAngle < 0) { |
- config.startAngle += 360; |
- } |
- while (config.startAngle > 360) { |
- config.startAngle -= 360; |
- } |
- while (realStartAngle < 0) { |
- realStartAngle += 2 * Math.PI; |
- } |
- while (realStartAngle > 2 * Math.PI) { |
- realStartAngle -= 2 * Math.PI; |
- } |
- config.logarithmic = false; |
- config.logarithmic2 = false; |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- defMouse(ctx, data, config); |
- setRect(ctx, config); |
- valueBounds = getValueBounds(); |
- //Check and set the scale |
- labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : ""; |
- if (!config.scaleOverride) { |
- calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, false, true, "PolarArea"); |
- } else { |
- calculatedScale = { |
- steps: config.scaleSteps, |
- stepValue: config.scaleStepWidth, |
- graphMin: config.scaleStartValue, |
- graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth, |
- labels: [] |
- } |
- populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, false, true, "PolarArea"); |
- } |
- midPosX = msr.leftNotUsableSize + (msr.availableWidth / 2); |
- midPosY = msr.topNotUsableSize + (msr.availableHeight / 2); |
- scaleHop = Math.floor(((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5) / calculatedScale.steps); |
- //Wrap in an animation loop wrapper |
- if(scaleHop > 0) { |
- animationLoop(config, drawScale, drawAllSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPosX, midPosY, midPosX - ((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5), midPosY + ((Min([msr.availableHeight, msr.availableWidth]) / 2) - 5), data); |
- } else { |
- testRedraw(ctx,data,config); |
- } |
- |
- function drawAllSegments(animationDecimal) { |
- var startAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI, |
- cumvalue = 0, |
- angleStep = 0, |
- scaleAnimation = 1, |
- rotateAnimation = 1; |
- angleStep = 0; |
- for (var i = 0; i < data.length; i++) |
- if (!(typeof(data[i].value) == 'undefined')) angleStep++; |
- angleStep = (Math.PI * 2) / angleStep; |
- while (startAngle < 0) { |
- startAngle += 2 * Math.PI; |
- } |
- while (startAngle > 2 * Math.PI) { |
- startAngle -= 2 * Math.PI; |
- } |
- if (config.animation) { |
- if (config.animateScale) { |
- scaleAnimation = animationDecimal; |
- } |
- if (config.animateRotate) { |
- rotateAnimation = animationDecimal; |
- } |
- } |
- if (animationDecimal >= 1) { |
- totvalue = 0; |
- for (var i = 0; i < data.length; i++) |
- if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value; |
- } |
- for (var i = 0; i < data.length; i++) { |
- correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal; |
- if (!(typeof(data[i].value) == 'undefined')) { |
- ctx.beginPath(); |
- ctx.arc(midPosX, midPosY, scaleAnimation * calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop), startAngle, startAngle + correctedRotateAnimation * angleStep, false); |
- ctx.lineTo(midPosX, midPosY); |
- ctx.closePath(); |
- if (typeof data[i].color == "function") ctx.fillStyle = data[i].color("COLOR", data, config, i, -1, animationDecimal, data[i].value, "PolarArea", ctx, midPosX, midPosY, 0, scaleAnimation * calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop)); |
- else ctx.fillStyle = data[i].color; |
- ctx.fill(); |
- startAngle += angleStep; |
- if (config.segmentShowStroke) { |
- ctx.strokeStyle = config.segmentStrokeColor; |
- ctx.lineWidth = config.segmentStrokeWidth; |
- ctx.stroke(); |
- } |
- } |
- } |
- if (animationDecimal >= 1) { |
- startAngle -= 2*Math.PI; |
- for (var i = 0; i < data.length; i++) { |
- if (!(typeof(data[i].value) == 'undefined')) { |
- cumvalue += 1 * data[i].value; |
- startAngle += angleStep; |
- if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim(); |
- else lgtxt = ""; |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", midPosX, midPosY, 0, calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop), startAngle - angleStep, startAngle, lgtxt, 1 * data[i].value, cumvalue, totvalue, angleStep, i]; |
- if (config.inGraphDataShow) { |
- if (config.inGraphDataAnglePosition == 1) posAngle = realStartAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 2) posAngle = realStartAngle - angleStep / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 3) posAngle = realStartAngle - angleStep + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- if (config.inGraphDataRadiusPosition == 1) labelRadius = 0 + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 2) labelRadius = calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop) / 2 + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 3) labelRadius = calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop) + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 4) labelRadius = scaleHop * calculatedScale.steps + config.inGraphDataPaddingRadius; |
- ctx.save() |
- if (config.inGraphDataAlign == "off-center") { |
- if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left"; |
- else ctx.textAlign = "right"; |
- } else if (config.inGraphDataAlign == "to-center") { |
- if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right"; |
- else ctx.textAlign = "left"; |
- } else ctx.textAlign = config.inGraphDataAlign; |
- if (config.inGraphDataVAlign == "off-center") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top"; |
- else ctx.textBaseline = "bottom"; |
- } else if (config.inGraphDataVAlign == "to-center") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom"; |
- else ctx.textBaseline = "top"; |
- } else ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2), |
- v3: fmtChartJS(config, cumvalue, config.fmtV3), |
- v4: fmtChartJS(config, totvalue, config.fmtV4), |
- v5: fmtChartJS(config, angleStep, config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, midPosX, config.fmtV7), |
- v8: fmtChartJS(config, midPosY, config.fmtV8), |
- v9: fmtChartJS(config, 0, config.fmtV9), |
- v10: fmtChartJS(config, calculateOffset(config.logarithmic, 1 * data[i].value, calculatedScale, scaleHop), config.fmtV10), |
- v11: fmtChartJS(config, startAngle - angleStep, config.fmtV11), |
- v12: fmtChartJS(config, angleStep, config.fmtV12), |
- v13: fmtChartJS(config, i, config.fmtV13), |
- data: data |
- }); |
- ctx.translate(midPosX + labelRadius * Math.cos(posAngle), midPosY - labelRadius * Math.sin(posAngle)); |
- if (config.inGraphDataRotate == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle); |
- else if (config.inGraphDataRotate == "inRadiusAxisRotateLabels") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle); |
- else ctx.rotate(2 * Math.PI - posAngle); |
- } else ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- ctx.restore(); |
- } |
- realStartAngle -= angleStep; |
- } |
- } |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"PolarArea"); |
- }; |
- |
- function drawScale() { |
- for (var i = 0; i < calculatedScale.steps; i++) { |
- //If the line object is there |
- if (config.scaleShowLine) { |
- ctx.beginPath(); |
- ctx.arc(midPosX, midPosY, scaleHop * (i + 1), 0, (Math.PI * 2), true); |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.stroke(); |
- } |
- if (config.scaleShowLabels) { |
- ctx.textAlign = "center"; |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- var label = calculatedScale.labels[i + 1]; |
- //If the backdrop object is within the font object |
- if (config.scaleShowLabelBackdrop) { |
- var textWidth = ctx.measureTextMultiLine(label, config.scaleFontSize).textWidth; |
- ctx.fillStyle = config.scaleBackdropColor; |
- ctx.beginPath(); |
- ctx.rect( |
- Math.round(midPosX - textWidth / 2 - config.scaleBackdropPaddingX), //X |
- Math.round(midPosY - (scaleHop * (i + 1)) - config.scaleFontSize * 0.5 - config.scaleBackdropPaddingY), //Y |
- Math.round(textWidth + (config.scaleBackdropPaddingX * 2)), //Width |
- Math.round(config.scaleFontSize + (config.scaleBackdropPaddingY * 2)) //Height |
- ); |
- ctx.fill(); |
- } |
- ctx.textBaseline = "middle"; |
- ctx.fillStyle = config.scaleFontColor; |
- ctx.fillTextMultiLine(label, midPosX, midPosY - (scaleHop * (i + 1)), ctx.textBaseline, config.scaleFontSize); |
- } |
- } |
- }; |
- |
- function getValueBounds() { |
- var upperValue = Number.MIN_VALUE; |
- var lowerValue = Number.MAX_VALUE; |
- for (var i = 0; i < data.length; i++) { |
- if (1 * data[i].value > upperValue) { |
- upperValue = 1 * data[i].value; |
- } |
- if (1 * data[i].value < lowerValue) { |
- lowerValue = 1 * data[i].value; |
- } |
- }; |
- if (Math.abs(upperValue - lowerValue) < 0.00000001) { |
- upperValue = Max([upperValue * 2, 1]); |
- lowerValue = 0; |
- } |
- if (!isNaN(config.graphMin)) lowerValue = config.graphMin; |
- if (!isNaN(config.graphMax)) upperValue = config.graphMax; |
- var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66))); |
- var minSteps = Math.floor((scaleHeight / labelHeight * 0.5)); |
- return { |
- maxValue: upperValue, |
- minValue: lowerValue, |
- maxSteps: maxSteps, |
- minSteps: minSteps |
- }; |
- }; |
- }; |
- var Radar = function(data, config, ctx) { |
- var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, msr, midPosX, midPosY; |
- |
- ctx.tpchart="Radar"; |
- setting_new_chart_vars(ctx); |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- while (config.startAngle < 0) { |
- config.startAngle += 360; |
- } |
- while (config.startAngle > 360) { |
- config.startAngle -= 360; |
- } |
- config.logarithmic = false; |
- config.logarithmic2 = false; |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- defMouse(ctx, data, config); |
- //If no labels are defined set to an empty array, so referencing length for looping doesn't blow up. |
- if (!data.labels) data.labels = []; |
- setRect(ctx, config); |
- valueBounds = getValueBounds(); |
- //Check and set the scale |
- labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : ""; |
- if (!config.scaleOverride) { |
- calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, true, config.datasetFill, "Radar"); |
- } else { |
- calculatedScale = { |
- steps: config.scaleSteps, |
- stepValue: config.scaleStepWidth, |
- graphMin: config.scaleStartValue, |
- graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth, |
- labels: [] |
- } |
- populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, false, true, config.datasetFill, "Radar"); |
- } |
- |
- |
- calculateDrawingSizes(); |
- midPosY = msr.topNotUsableSize + (msr.availableHeight / 2); |
- scaleHop = maxSize / (calculatedScale.steps); |
- //Wrap in an animation loop wrapper |
- animationLoop(config, drawScale, drawAllDataPoints, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPosX, midPosY, midPosX - maxSize, midPosY + maxSize, data); |
- //Radar specific functions. |
- function drawAllDataPoints(animationDecimal) { |
- var totvalue = new Array(); |
- var maxvalue = new Array(); |
- var lmaxvalue = new Array(); |
- for (var i = 0; i < data.datasets.length; i++) { |
- lmaxvalue[i] = -999999999; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- totvalue[j] = 0; |
- maxvalue[j] = -999999999; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- totvalue[j] += 1 * data.datasets[i].data[j]; |
- maxvalue[j] = Max([maxvalue[j], 1 * data.datasets[i].data[j]]); |
- lmaxvalue[i] = Max([lmaxvalue[i], 1 * data.datasets[i].data[j]]); |
- } |
- } |
- } |
- var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length; |
- ctx.save(); |
- //We accept multiple data sets for radar charts, so show loop through each set |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (animationDecimal >= 1) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- } |
- var fPt = -1; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- var currentAnimPc = animationCorrection(animationDecimal, data, config, i, j, 1).animVal; |
- if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1; |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- if (fPt == -1) { |
- ctx.beginPath(); |
- ctx.moveTo(midPosX + currentAnimPc * (Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)), midPosY - currentAnimPc * (Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop))); |
- fPt = j; |
- } else { |
- ctx.lineTo(midPosX + currentAnimPc * (Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)), midPosY - currentAnimPc * (Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop))); |
- } |
- if (animationDecimal >= 1) { |
- if (i == 0) divprev = 0; |
- else divprev = data.datasets[i].data[j] - data.datasets[i - 1].data[j]; |
- if (i == data.datasets.length - 1) divnext = 0; |
- else divnext = data.datasets[i + 1].data[j] - data.datasets[i].data[j]; |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- else lgtxt2 = ""; |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["POINT", midPosX + Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop), midPosY - Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop), lgtxt, lgtxt2, 1 * data.datasets[i].data[j], divprev, divnext, maxvalue[j], totvalue[j], i, j]; |
- } |
- } |
- } |
- ctx.closePath(); |
- if (config.datasetFill) { |
- if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, -1, currentAnimPc, -1, "Radar", ctx, midPosX, midPosY, 0, (config.animationLeftToRight ? 1 : currentAnimPc) * (calculateOffset(config.logarithmic, lmaxvalue[i], calculatedScale, scaleHop))); |
- else if (typeof data.datasets[i].fillColor == "string") ctx.fillStyle = data.datasets[i].fillColor; |
- else ctx.fillStyle = config.defaultFillColor; |
- } else ctx.fillStyle = "rgba(0,0,0,0)"; |
- if (typeof data.datasets[i].strokeColor == "function") ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, -1, currentAnimPc, -1, "Radar", ctx, midPosX, midPosY, 0, (config.animationLeftToRight ? 1 : currentAnimPc) * (calculateOffset(config.logarithmic, lmaxvalue[i], calculatedScale, scaleHop))); |
- else if (typeof data.datasets[i].strokeColor == "string") ctx.strokeStyle = data.datasets[i].strokeColor; |
- else ctx.strokeStyle = config.defaultStrokeColor; |
- ctx.lineWidth = config.datasetStrokeWidth; |
- ctx.fill(); |
- ctx.stroke(); |
- if (config.pointDot && (!config.animationLeftToRight || (config.animationLeftToRight && animationDecimal >= 1))) { |
- ctx.beginPath(); |
- if (typeof data.datasets[i].pointColor == "function") ctx.fillStyle = data.datasets[i].pointColor("POINTCOLOR", data, config, i, -1, currentAnimPc, -1, "Radar", ctx, midPosX, midPosY, 0, (config.animationLeftToRight ? 1 : currentAnimPc) * (calculateOffset(config.logarithmic, lmaxvalue[i], calculatedScale, scaleHop))); |
- else ctx.fillStyle = data.datasets[i].pointColor; |
- if (typeof data.datasets[i].pointStrokeColor == "function") ctx.strokeStyle = data.datasets[i].pointStrokeColor("POINTSTROKECOLOR", data, config, i, -1, currentAnimPc, -1, "Radar", ctx, midPosX, midPosY, 0, (config.animationLeftToRight ? 1 : currentAnimPc) * (calculateOffset(config.logarithmic, lmaxvalue[i], calculatedScale, scaleHop))); |
- else ctx.strokeStyle = data.datasets[i].pointStrokeColor; |
- ctx.lineWidth = config.pointDotStrokeWidth; |
- for (var k = 0; k < data.datasets[i].data.length; k++) { |
- if (!(typeof(data.datasets[i].data[k]) == 'undefined')) { |
- ctx.beginPath(); |
- ctx.arc(midPosX + currentAnimPc * (Math.cos(config.startAngle * Math.PI / 180 - k * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[k], calculatedScale, scaleHop)), midPosY - currentAnimPc * (Math.sin(config.startAngle * Math.PI / 180 - k * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[k], calculatedScale, scaleHop)), config.pointDotRadius, 2 * Math.PI, false); |
- ctx.fill(); |
- ctx.stroke(); |
- } |
- } |
- } |
- } |
- ctx.restore(); |
- if (animationDecimal >= 1 && config.inGraphDataShow) { |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- if (i == 0) divprev = 0; |
- else divprev = data.datasets[i].data[j] - data.datasets[i - 1].data[j]; |
- if (i == data.datasets.length - 1) divnext = 0; |
- else divnext = data.datasets[i + 1].data[j] - data.datasets[i].data[j]; |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- else lgtxt2 = ""; |
- ctx.save(); |
- ctx.textAlign = config.inGraphDataAlign; |
- ctx.textBaseline = config.inGraphDataVAlign; |
- if (config.inGraphDataAlign == "off-center") { |
- if (config.inGraphDataRotate == "inRadiusAxis" || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) <= Math.PI / 2) ctx.textAlign = "left"; |
- else ctx.textAlign = "right"; |
- } else if (config.inGraphDataAlign == "to-center") { |
- if (config.inGraphDataRotate == "inRadiusAxis" || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right"; |
- else ctx.textAlign = "left"; |
- } else ctx.textAlign = config.inGraphDataAlign; |
- if (config.inGraphDataVAlign == "off-center") { |
- if ((config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom"; |
- else ctx.textBaseline = "top"; |
- } else if (config.inGraphDataVAlign == "to-center") { |
- if ((config.startAngle * Math.PI / 180 - j * rotationDegree + 4 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top"; |
- else ctx.textBaseline = "bottom"; |
- } else ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- var radiusPrt; |
- if (config.inGraphDataRadiusPosition == 1) radiusPrt = 0 + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 2) radiusPrt = (calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)) / 2 + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 3) radiusPrt = (calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)) + config.inGraphDataPaddingRadius; |
- ctx.translate(midPosX + Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * radiusPrt, midPosY - Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * radiusPrt); |
- if (config.inGraphDataRotate == "inRadiusAxis") ctx.rotate(j * rotationDegree); |
- else if (config.inGraphDataRotate == "inRadiusAxisRotateLabels") { |
- if ((j * rotationDegree + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (j * rotationDegree + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI + j * rotationDegree); |
- else ctx.rotate(2 * Math.PI + j * rotationDegree); |
- } else ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, lgtxt2, config.fmtV2), |
- v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3), |
- v4: fmtChartJS(config, divprev, config.fmtV4), |
- v5: fmtChartJS(config, divnext, config.fmtV5), |
- v6: fmtChartJS(config, maxvalue[j], config.fmtV6), |
- v7: fmtChartJS(config, totvalue[j], config.fmtV7), |
- v8: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV8), config.roundPct), |
- v9: fmtChartJS(config, midPosX + Math.cos(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop), config.fmtV9), |
- v10: fmtChartJS(config, midPosY - Math.sin(config.startAngle * Math.PI / 180 - j * rotationDegree) * calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop), config.fmtV10), |
- v11: fmtChartJS(config, i, config.fmtV11), |
- v12: fmtChartJS(config, j, config.fmtV12), |
- data: data |
- }); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- ctx.restore(); |
- } |
- } |
- } |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Radar"); |
- }; |
- |
- function drawScale() { |
- var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length; |
- ctx.save(); |
- ctx.translate(midPosX, midPosY); |
- ctx.rotate((90 - config.startAngle) * Math.PI / 180); |
- if (config.angleShowLineOut) { |
- ctx.strokeStyle = config.angleLineColor; |
- ctx.lineWidth = config.angleLineWidth; |
- for (var h = 0; h < data.datasets[0].data.length; h++) { |
- ctx.rotate(rotationDegree); |
- ctx.beginPath(); |
- ctx.moveTo(0, 0); |
- ctx.lineTo(0, -maxSize); |
- ctx.stroke(); |
- } |
- } |
- for (var i = 0; i < calculatedScale.steps; i++) { |
- ctx.beginPath(); |
- if (config.scaleShowLine) { |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.moveTo(0, -scaleHop * (i + 1)); |
- for (var j = 0; j < data.datasets[0].data.length; j++) { |
- ctx.rotate(rotationDegree); |
- ctx.lineTo(0, -scaleHop * (i + 1)); |
- } |
- ctx.closePath(); |
- ctx.stroke(); |
- } |
- } |
- ctx.rotate(-(90 - config.startAngle) * Math.PI / 180); |
- if (config.scaleShowLabels) { |
- for (var i = 0; i < calculatedScale.steps; i++) { |
- ctx.textAlign = 'center'; |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- ctx.textBaseline = "middle"; |
- if (config.scaleShowLabelBackdrop) { |
- var textWidth = ctx.measureTextMultiLine(calculatedScale.labels[i + 1], config.scaleFontSize).textWidth; |
- ctx.fillStyle = config.scaleBackdropColor; |
- ctx.beginPath(); |
- ctx.rect( |
- Math.round(Math.cos(config.startAngle * Math.PI / 180) * (scaleHop * (i + 1)) - textWidth / 2 - config.scaleBackdropPaddingX), //X |
- Math.round((-Math.sin(config.startAngle * Math.PI / 180) * scaleHop * (i + 1)) - config.scaleFontSize * 0.5 - config.scaleBackdropPaddingY), //Y |
- Math.round(textWidth + (config.scaleBackdropPaddingX * 2)), //Width |
- Math.round(config.scaleFontSize + (config.scaleBackdropPaddingY * 2)) //Height |
- ); |
- ctx.fill(); |
- } |
- ctx.fillStyle = config.scaleFontColor; |
- ctx.fillTextMultiLine(calculatedScale.labels[i + 1], Math.cos(config.startAngle * Math.PI / 180) * (scaleHop * (i + 1)), -Math.sin(config.startAngle * Math.PI / 180) * scaleHop * (i + 1), ctx.textBaseline, config.scaleFontSize); |
- } |
- } |
- for (var k = 0; k < data.labels.length; k++) { |
- ctx.font = config.pointLabelFontStyle + " " + config.pointLabelFontSize + "px " + config.pointLabelFontFamily; |
- ctx.fillStyle = config.pointLabelFontColor; |
- var opposite = Math.sin((90 - config.startAngle) * Math.PI / 180 + rotationDegree * k) * (maxSize + config.pointLabelFontSize); |
- var adjacent = Math.cos((90 - config.startAngle) * Math.PI / 180 + rotationDegree * k) * (maxSize + config.pointLabelFontSize); |
- var vangle = (90 - config.startAngle) * Math.PI / 180 + rotationDegree * k; |
- while (vangle < 0) vangle = vangle + 2 * Math.PI; |
- while (vangle > 2 * Math.PI) vangle = vangle - 2 * Math.PI; |
- if (vangle == Math.PI || vangle == 0) { |
- ctx.textAlign = "center"; |
- } else if (vangle > Math.PI) { |
- ctx.textAlign = "right"; |
- } else { |
- ctx.textAlign = "left"; |
- } |
- ctx.textBaseline = "middle"; |
- ctx.fillTextMultiLine(data.labels[k], opposite, -adjacent, ctx.textBaseline, config.pointLabelFontSize); |
- } |
- ctx.restore(); |
- }; |
- |
- function calculateDrawingSizes() { |
- var midX, mxlb, maxL, maxR, iter, nbiter, prevMaxSize, prevMidX; |
- var rotationDegree = (2 * Math.PI) / data.datasets[0].data.length; |
- var rotateAngle = config.startAngle * Math.PI / 180; |
- // Compute range for Mid Point of graph |
- ctx.font = config.pointLabelFontStyle + " " + config.pointLabelFontSize + "px " + config.pointLabelFontFamily; |
- if (!config.graphMaximized) { |
- maxR = msr.availableWidth / 2; |
- maxL = msr.availableWidth / 2; |
- nbiter = 1; |
- } else { |
- maxR = msr.availableWidth / 2; |
- maxL = msr.availableWidth / 2; |
- nbiter = 40; |
- for (var i = 0; i < data.labels.length; i++) { |
- var textMeasurement = ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textWidth + ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textHeight; |
- mxlb = (msr.availableWidth - textMeasurement) / (1 + Math.abs(Math.cos(rotateAngle))); |
- if ((rotateAngle < Math.PI / 2 && rotateAngle > -Math.PI / 2) || rotateAngle > 3 * Math.PI / 2) { |
- if (mxlb < maxR) maxR = mxlb; |
- } else if (Math.cos(rotateAngle) != 0) { |
- if (mxlb < maxL) maxL = mxlb; |
- } |
- rotateAngle -= rotationDegree; |
- } |
- } |
- // compute max Radius and midPoint in that range |
- prevMaxSize = 0; |
- prevMidX = 0; |
- midPosX = maxR + msr.rightNotUsableSize; |
- for (midX = maxR, iter = 0; iter < nbiter; ++iter, midX += (msr.availableWidth - maxL - maxR) / nbiter) { |
- maxSize = Max([midX, msr.availableWidth - midX]); |
- var rotateAngle = config.startAngle * Math.PI / 180; |
- mxlb = msr.available; |
- for (var i = 0; i < data.labels.length; i++) { |
- var textMeasurement = ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textWidth + ctx.measureTextMultiLine(data.labels[i], config.scaleFontSize).textHeight; |
- if ((rotateAngle < Math.PI / 2 && rotateAngle > -Math.PI / 2) || rotateAngle > 3 * Math.PI / 2) { |
- mxlb = ((msr.availableWidth - midX) - textMeasurement) / Math.abs(Math.cos(rotateAngle)); |
- } else if (Math.cos(rotateAngle != 0)) { |
- mxlb = (midX - textMeasurement) / Math.abs(Math.cos(rotateAngle)); |
- } |
- if (mxlb < maxSize) maxSize = mxlb; |
- if (Math.sin(rotateAngle) * msr.availableHeight / 2 > msr.availableHeight / 2 - config.scaleFontSize * 2) { |
- mxlb = Math.sin(rotateAngle) * msr.availableHeight / 2 - 1.5 * config.scaleFontSize; |
- if (mxlb < maxSize) maxSize = mxlb; |
- } |
- rotateAngle -= rotationDegree; |
- } |
- if (maxSize > prevMaxSize) { |
- prevMaxSize = maxSize; |
- midPosX = midX + msr.rightNotUsableSize; |
- } |
- } |
- maxSize = prevMaxSize - config.scaleFontSize / 2; |
- //If the label height is less than 5, set it to 5 so we don't have lines on top of each other. |
- labelHeight = Default(labelHeight, 5); |
- }; |
- |
- function getValueBounds() { |
- var upperValue = Number.MIN_VALUE; |
- var lowerValue = Number.MAX_VALUE; |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (1 * data.datasets[i].data[j] > upperValue) { |
- upperValue = 1 * data.datasets[i].data[j] |
- } |
- if (1 * data.datasets[i].data[j] < lowerValue) { |
- lowerValue = 1 * data.datasets[i].data[j] |
- } |
- } |
- } |
- if (Math.abs(upperValue - lowerValue) < 0.00000001) { |
- upperValue = Max([upperValue * 2, 1]); |
- lowerValue = 0; |
- } |
- if (!isNaN(config.graphMin)) lowerValue = config.graphMin; |
- if (!isNaN(config.graphMax)) upperValue = config.graphMax; |
- var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66))); |
- var minSteps = Math.floor((scaleHeight / labelHeight * 0.5)); |
- return { |
- maxValue: upperValue, |
- minValue: lowerValue, |
- maxSteps: maxSteps, |
- minSteps: minSteps |
- }; |
- } |
- }; |
- |
- |
- var Pie = function(data, config, ctx) { |
- |
- var segmentTotal = 0; |
- var msr, midPieX, midPieY, pieRadius; |
- |
- ctx.tpchart="Pie"; |
- setting_new_chart_vars(ctx); |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- while (config.startAngle < 0) { |
- config.startAngle += 360; |
- } |
- while (config.startAngle > 360) { |
- config.startAngle -= 360; |
- } |
- config.logarithmic = false; |
- config.logarithmic2 = false; |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- defMouse(ctx, data, config); |
- //In case we have a canvas that is not a square. Minus 5 pixels as padding round the edge. |
- setRect(ctx, config); |
- msr = setMeasures(data, config, ctx, height, width, "none", null, true, false, false, false, true, "Pie"); |
- // midPieX = msr.leftNotUsableSize + (msr.availableWidth / 2); |
- // midPieY = msr.topNotUsableSize + (msr.availableHeight / 2); |
- // pieRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - 5; |
- for (var i = 0; i < data.length; i++) { |
- if (!(typeof(data[i].value) == 'undefined')) segmentTotal += 1 * data[i].value; |
- } |
- calculateDrawingSize(); |
- if(pieRadius > 0) { |
- animationLoop(config, null, drawPieSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPieX, midPieY, midPieX - pieRadius, midPieY + pieRadius, data); |
- } else { |
- testRedraw(ctx,data,config); |
- } |
- function drawPieSegments(animationDecimal) { |
- var cumulativeAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI, |
- cumvalue = 0, |
- scaleAnimation = 1, |
- rotateAnimation = 1; |
- var realCumulativeAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI; |
- while (cumulativeAngle < 0) { |
- cumulativeAngle += 2 * Math.PI; |
- } |
- while (cumulativeAngle > 2 * Math.PI) { |
- cumulativeAngle -= 2 * Math.PI; |
- } |
- while (realCumulativeAngle < 0) { |
- realCumulativeAngle += 2 * Math.PI; |
- } |
- while (realCumulativeAngle > 2 * Math.PI) { |
- realCumulativeAngle -= 2 * Math.PI; |
- } |
- if (config.animation) { |
- if (config.animateScale) { |
- scaleAnimation = animationDecimal; |
- } |
- if (config.animateRotate) { |
- rotateAnimation = animationDecimal; |
- } |
- } |
- if (animationDecimal >= 1) { |
- totvalue = 0; |
- for (var i = 0; i < data.length; i++) |
- if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value; |
- } |
- for (var i = 0; i < data.length; i++) { |
- correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal; |
- if (!(typeof(data[i].value) == 'undefined')) { |
- var segmentAngle = correctedRotateAnimation * ((1 * data[i].value / segmentTotal) * (Math.PI * 2)); |
- if (segmentAngle >= Math.PI * 2) segmentAngle = Math.PI * 2 - 0.001; // bug on Android when segmentAngle is >= 2*PI; |
- ctx.beginPath(); |
- ctx.arc(midPieX, midPieY, scaleAnimation * pieRadius, cumulativeAngle, cumulativeAngle + segmentAngle); |
- ctx.lineTo(midPieX, midPieY); |
- ctx.closePath(); |
- if (typeof data[i].color == "function") ctx.fillStyle = data[i].color("COLOR", data, config, i, -1, animationDecimal, data[i].value, "Pie", ctx, midPieX, midPieY, 0, scaleAnimation * pieRadius); |
- else ctx.fillStyle = data[i].color; |
- ctx.fill(); |
- cumulativeAngle += segmentAngle; |
- cumvalue += 1 * data[i].value; |
- if (config.segmentShowStroke) { |
- ctx.lineWidth = config.segmentStrokeWidth; |
- ctx.strokeStyle = config.segmentStrokeColor; |
- ctx.stroke(); |
- } |
- } |
- } |
- if (animationDecimal >= 1) { |
- cumulativeAngle-=2*Math.PI; |
- for (var i = 0; i < data.length; i++) { |
- correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal; |
- if (!(typeof(data[i].value) == 'undefined')) { |
- var segmentAngle = correctedRotateAnimation * ((1 * data[i].value / segmentTotal) * (Math.PI * 2)); |
- if (segmentAngle >= Math.PI * 2) segmentAngle = Math.PI * 2 - 0.001; // bug on Android when segmentAngle is >= 2*PI; |
- cumulativeAngle += segmentAngle; |
- cumvalue += 1 * data[i].value; |
- if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim(); |
- else lgtxt = ""; |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", midPieX, midPieY, 0, pieRadius, cumulativeAngle - segmentAngle, cumulativeAngle, lgtxt, 1 * data[i].value, cumvalue, totvalue, segmentAngle, i]; |
- if (config.inGraphDataShow && segmentAngle >= (Math.PI/180) * config.inGraphDataMinimumAngle) { |
- if (config.inGraphDataAnglePosition == 1) posAngle = realCumulativeAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 2) posAngle = realCumulativeAngle - segmentAngle / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 3) posAngle = realCumulativeAngle - segmentAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- if (config.inGraphDataRadiusPosition == 1) labelRadius = 0 + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 2) labelRadius = pieRadius / 2 + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 3) labelRadius = pieRadius + config.inGraphDataPaddingRadius; |
- ctx.save(); |
- if (config.inGraphDataAlign == "off-center") { |
- if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left"; |
- else ctx.textAlign = "right"; |
- } else if (config.inGraphDataAlign == "to-center") { |
- if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right"; |
- else ctx.textAlign = "left"; |
- } else ctx.textAlign = config.inGraphDataAlign; |
- if (config.inGraphDataVAlign == "off-center") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top"; |
- else ctx.textBaseline = "bottom"; |
- } else if (config.inGraphDataVAlign == "to-center") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom"; |
- else ctx.textBaseline = "top"; |
- } else ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2), |
- v3: fmtChartJS(config, cumvalue, config.fmtV3), |
- v4: fmtChartJS(config, totvalue, config.fmtV4), |
- v5: fmtChartJS(config, segmentAngle, config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, midPieX, config.fmtV7), |
- v8: fmtChartJS(config, midPieY, config.fmtV8), |
- v9: fmtChartJS(config, 0, config.fmtV9), |
- v10: fmtChartJS(config, pieRadius, config.fmtV10), |
- v11: fmtChartJS(config, cumulativeAngle - segmentAngle, config.fmtV11), |
- v12: fmtChartJS(config, cumulativeAngle, config.fmtV12), |
- v13: fmtChartJS(config, i, config.fmtV13), |
- data: data |
- }); |
- ctx.translate(midPieX + labelRadius * Math.cos(posAngle), midPieY - labelRadius * Math.sin(posAngle)); |
- if (config.inGraphDataRotate == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle); |
- else if (config.inGraphDataRotate == "inRadiusAxisRotateLabels") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle); |
- else ctx.rotate(2 * Math.PI - posAngle); |
- } else ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- ctx.restore(); |
- } |
- realCumulativeAngle -= segmentAngle; |
- } |
- } |
- |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Pie"); |
- }; |
- |
- function calculateDrawingSize() { |
- var lgtxt; |
- var cumulativeAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI, |
- cumvalue = 0; |
- while (cumulativeAngle < 0) { |
- cumulativeAngle += 2 * Math.PI; |
- } |
- while (cumulativeAngle > 2 * Math.PI) { |
- cumulativeAngle -= 2 * Math.PI; |
- } |
- midPieX = msr.leftNotUsableSize + (msr.availableWidth / 2); |
- midPieY = msr.topNotUsableSize + (msr.availableHeight / 2); |
- pieRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - 5; |
- // Computerange Pie Radius |
- if (config.inGraphDataShow && config.inGraphDataRadiusPosition == 3 && config.inGraphDataAlign == "off-center" && config.inGraphDataRotate == 0) { |
- pieRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - config.inGraphDataFontSize - config.inGraphDataPaddingRadius - 5; |
- var realCumulativeAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI; |
- while (realCumulativeAngle < 0) { |
- realCumulativeAngle += 2 * Math.PI; |
- } |
- while (realCumulativeAngle > 2 * Math.PI) { |
- realCumulativeAngle -= 2 * Math.PI; |
- } |
- var totvalue = 0; |
- for (var i = 0; i < data.length; i++) |
- if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- var cumvalue = 0; |
- var posAngle; |
- for (var i = 0; i < data.length; i++) { |
- if (!(typeof(data[i].value) == 'undefined')) { |
- cumvalue += 1 * data[i].value; |
- var segmentAngle = (1 * data[i].value / segmentTotal) * (Math.PI * 2); |
- cumulativeAngle += segmentAngle; |
- if (config.inGraphDataAnglePosition == 1) posAngle = realCumulativeAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 2) posAngle = realCumulativeAngle - segmentAngle / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 3) posAngle = realCumulativeAngle - segmentAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- realCumulativeAngle -= segmentAngle; |
- if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim(); |
- else lgtxt = ""; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2), |
- v3: fmtChartJS(config, cumvalue, config.fmtV3), |
- v4: fmtChartJS(config, totvalue, config.fmtV4), |
- v5: fmtChartJS(config, segmentAngle, config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, midPieX, config.fmtV7), |
- v8: fmtChartJS(config, midPieY, config.fmtV8), |
- v9: fmtChartJS(config, 0, config.fmtV9), |
- v10: fmtChartJS(config, pieRadius, config.fmtV10), |
- v11: fmtChartJS(config, cumulativeAngle - segmentAngle, config.fmtV11), |
- v12: fmtChartJS(config, cumulativeAngle, config.fmtV12), |
- v13: fmtChartJS(config, i, config.fmtV13), |
- data: data |
- }); |
- var textMeasurement = ctx.measureText(dispString).width; |
- var MaxRadiusX = Math.abs((msr.availableWidth / 2 - textMeasurement) / Math.cos(posAngle)) - config.inGraphDataPaddingRadius - 5; |
- if (MaxRadiusX < pieRadius) pieRadius = MaxRadiusX; |
- } |
- } |
- } |
- pieRadius = pieRadius * config.radiusScale; |
- }; |
- }; |
- var Doughnut = function(data, config, ctx) { |
- var segmentTotal = 0; |
- var msr, midPieX, midPieY, doughnutRadius; |
- |
- ctx.tpchart="Doughnut"; |
- setting_new_chart_vars(ctx); |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- var realCumulativeAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI; |
- while (config.startAngle < 0) { |
- config.startAngle += 360; |
- } |
- while (config.startAngle > 360) { |
- config.startAngle -= 360; |
- } |
- while (realCumulativeAngle < 0) { |
- realCumulativeAngle += 2 * Math.PI; |
- } |
- while (realCumulativeAngle > 2 * Math.PI) { |
- realCumulativeAngle -= 2 * Math.PI; |
- } |
- config.logarithmic = false; |
- config.logarithmic2 = false; |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- defMouse(ctx, data, config); |
- setRect(ctx, config); |
- msr = setMeasures(data, config, ctx, height, width, "none", null, true, false, false, false, true, "Doughnut"); |
- calculateDrawingSize(); |
- var cutoutRadius = doughnutRadius * (config.percentageInnerCutout / 100); |
- for (var i = 0; i < data.length; i++) { |
- if (!(typeof(data[i].value) == 'undefined')) segmentTotal += 1 * data[i].value; |
- } |
- if(doughnutRadius > 0) { |
- animationLoop(config, null, drawPieSegments, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, midPieX, midPieY, midPieX - doughnutRadius, midPieY + doughnutRadius, data); |
- } else { |
- testRedraw(ctx,data,config); |
- } |
- |
- |
- function drawPieSegments(animationDecimal) { |
- var cumulativeAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI, |
- cumvalue = 0, |
- scaleAnimation = 1, |
- rotateAnimation = 1; |
- while (cumulativeAngle < 0) { |
- cumulativeAngle += 2 * Math.PI; |
- } |
- while (cumulativeAngle > 2 * Math.PI) { |
- cumulativeAngle -= 2 * Math.PI; |
- } |
- if (config.animation) { |
- if (config.animateScale) { |
- scaleAnimation = animationDecimal; |
- } |
- if (config.animateRotate) { |
- rotateAnimation = animationDecimal; |
- } |
- } |
- if (animationDecimal >= 1) { |
- totvalue = 0; |
- for (var i = 0; i < data.length; i++) |
- if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value; |
- } |
- for (var i = 0; i < data.length; i++) { |
- correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal; |
- if (!(typeof(data[i].value) == 'undefined')) { |
- var segmentAngle = correctedRotateAnimation * ((1 * data[i].value / segmentTotal) * (Math.PI * 2)); |
- if (segmentAngle >= Math.PI * 2) segmentAngle = Math.PI * 2 - 0.001; // but on Android when segmentAngle is >= 2*PI; |
- ctx.beginPath(); |
- ctx.arc(midPieX, midPieY, scaleAnimation * doughnutRadius, cumulativeAngle, cumulativeAngle + segmentAngle, false); |
- ctx.arc(midPieX, midPieY, scaleAnimation * cutoutRadius, cumulativeAngle + segmentAngle, cumulativeAngle, true); |
- ctx.closePath(); |
- if (typeof data[i].color == "function") ctx.fillStyle = data[i].color("COLOR", data, config, i, -1, animationDecimal, data[i].value, "Doughnut", ctx, midPieX, midPieY, scaleAnimation * cutoutRadius, scaleAnimation * doughnutRadius); |
- else ctx.fillStyle = data[i].color; |
- ctx.fill(); |
- cumulativeAngle += segmentAngle; |
- cumvalue += 1 * data[i].value; |
- if (config.segmentShowStroke) { |
- ctx.lineWidth = config.segmentStrokeWidth; |
- ctx.strokeStyle = config.segmentStrokeColor; |
- ctx.stroke(); |
- } |
- } |
- } |
- if (animationDecimal >= 1) { |
- cumulativeAngle-=2*Math.PI; |
- for (var i = 0; i < data.length; i++) { |
- correctedRotateAnimation = animationCorrection(rotateAnimation, data, config, i, -1, 0).mainVal; |
- if (!(typeof(data[i].value) == 'undefined')) { |
- var segmentAngle = correctedRotateAnimation * ((1 * data[i].value / segmentTotal) * (Math.PI * 2)); |
- if (segmentAngle >= Math.PI * 2) segmentAngle = Math.PI * 2 - 0.001; // but on Android when segmentAngle is >= 2*PI; |
- cumulativeAngle += segmentAngle; |
- cumvalue += 1 * data[i].value; |
- if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim(); |
- else lgtxt = ""; |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["ARC", midPieX, midPieY, cutoutRadius, doughnutRadius, cumulativeAngle - segmentAngle, cumulativeAngle, lgtxt, 1 * data[i].value, cumvalue, totvalue, segmentAngle, i]; |
- if (config.inGraphDataShow && segmentAngle >= (Math.PI/180) * config.inGraphDataMinimumAngle) { |
- if (config.inGraphDataAnglePosition == 1) posAngle = realCumulativeAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 2) posAngle = realCumulativeAngle - segmentAngle / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 3) posAngle = realCumulativeAngle - segmentAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- if (config.inGraphDataRadiusPosition == 1) labelRadius = cutoutRadius + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 2) labelRadius = cutoutRadius + (doughnutRadius - cutoutRadius) / 2 + config.inGraphDataPaddingRadius; |
- else if (config.inGraphDataRadiusPosition == 3) labelRadius = doughnutRadius + config.inGraphDataPaddingRadius; |
- ctx.save(); |
- if (config.inGraphDataAlign == "off-center") { |
- if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "left"; |
- else ctx.textAlign = "right"; |
- } else if (config.inGraphDataAlign == "to-center") { |
- if (config.inGraphDataRotate == "inRadiusAxis" || (posAngle + 2 * Math.PI) % (2 * Math.PI) > 3 * Math.PI / 2 || (posAngle + 2 * Math.PI) % (2 * Math.PI) < Math.PI / 2) ctx.textAlign = "right"; |
- else ctx.textAlign = "left"; |
- } else ctx.textAlign = config.inGraphDataAlign; |
- if (config.inGraphDataVAlign == "off-center") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "top"; |
- else ctx.textBaseline = "bottom"; |
- } else if (config.inGraphDataVAlign == "to-center") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI) ctx.textBaseline = "bottom"; |
- else ctx.textBaseline = "top"; |
- } else ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2), |
- v3: fmtChartJS(config, cumvalue, config.fmtV3), |
- v4: fmtChartJS(config, totvalue, config.fmtV4), |
- v5: fmtChartJS(config, segmentAngle, config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, midPieX, config.fmtV7), |
- v8: fmtChartJS(config, midPieY, config.fmtV8), |
- v9: fmtChartJS(config, cutoutRadius, config.fmtV9), |
- v10: fmtChartJS(config, doughnutRadius, config.fmtV10), |
- v11: fmtChartJS(config, cumulativeAngle - segmentAngle, config.fmtV11), |
- v12: fmtChartJS(config, cumulativeAngle, config.fmtV12), |
- v13: fmtChartJS(config, i, config.fmtV13) |
- }); |
- ctx.translate(midPieX + labelRadius * Math.cos(posAngle), midPieY - labelRadius * Math.sin(posAngle)); |
- if (config.inGraphDataRotate == "inRadiusAxis") ctx.rotate(2 * Math.PI - posAngle); |
- else if (config.inGraphDataRotate == "inRadiusAxisRotateLabels") { |
- if ((posAngle + 2 * Math.PI) % (2 * Math.PI) > Math.PI / 2 && (posAngle + 2 * Math.PI) % (2 * Math.PI) < 3 * Math.PI / 2) ctx.rotate(3 * Math.PI - posAngle); |
- else ctx.rotate(2 * Math.PI - posAngle); |
- } else ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- ctx.restore(); |
- } |
- realCumulativeAngle -= segmentAngle; |
- } |
- } |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Doughnut"); |
- }; |
- |
- function calculateDrawingSize() { |
- var lgtxt; |
- var cumulativeAngle = -config.startAngle * (Math.PI / 180) + 2 * Math.PI, |
- cumvalue = 0; |
- while (cumulativeAngle < 0) { |
- cumulativeAngle += 2 * Math.PI; |
- } |
- while (cumulativeAngle > 2 * Math.PI) { |
- cumulativeAngle -= 2 * Math.PI; |
- } |
- midPieX = msr.leftNotUsableSize + (msr.availableWidth / 2); |
- midPieY = msr.topNotUsableSize + (msr.availableHeight / 2); |
- doughnutRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - 5; |
- // Computerange Pie Radius |
- if (config.inGraphDataShow && config.inGraphDataRadiusPosition == 3 && config.inGraphDataAlign == "off-center" && config.inGraphDataRotate == 0) { |
- doughnutRadius = Min([msr.availableHeight / 2, msr.availableWidth / 2]) - config.inGraphDataFontSize - config.inGraphDataPaddingRadius - 5; |
- var realCumulativeAngle = config.startAngle * (Math.PI / 180) + 2 * Math.PI; |
- while (realCumulativeAngle < 0) { |
- realCumulativeAngle += 2 * Math.PI; |
- } |
- while (realCumulativeAngle > 2 * Math.PI) { |
- realCumulativeAngle -= 2 * Math.PI; |
- } |
- var totvalue = 0; |
- for (var i = 0; i < data.length; i++) |
- if (!(typeof(data[i].value) == 'undefined')) totvalue += 1 * data[i].value; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- var posAngle; |
- var cumulativeAngle = 0; |
- for (var i = 0; i < data.length; i++) { |
- if (!(typeof(data[i].value) == 'undefined')) { |
- cumvalue += 1 * data[i].value; |
- var segmentAngle = (1 * data[i].value / segmentTotal) * (Math.PI * 2); |
- cumulativeAngle += segmentAngle; |
- if (config.inGraphDataAnglePosition == 1) posAngle = realCumulativeAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 2) posAngle = realCumulativeAngle - segmentAngle / 2 + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- else if (config.inGraphDataAnglePosition == 3) posAngle = realCumulativeAngle - segmentAngle + config.inGraphDataPaddingAngle * (Math.PI / 180); |
- realCumulativeAngle -= segmentAngle; |
- if (typeof(data[i].title) == "string") lgtxt = data[i].title.trim(); |
- else lgtxt = ""; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, 1 * data[i].value, config.fmtV2), |
- v3: fmtChartJS(config, cumvalue, config.fmtV3), |
- v4: fmtChartJS(config, totvalue, config.fmtV4), |
- v5: fmtChartJS(config, segmentAngle, config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, 100 * data[i].value / totvalue, config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, midPieX, config.fmtV7), |
- v8: fmtChartJS(config, midPieY, config.fmtV8), |
- v9: fmtChartJS(config, cutoutRadius, config.fmtV9), |
- v10: fmtChartJS(config, doughnutRadius, config.fmtV10), |
- v11: fmtChartJS(config, cumulativeAngle - segmentAngle, config.fmtV11), |
- v12: fmtChartJS(config, cumulativeAngle, config.fmtV12), |
- v13: fmtChartJS(config, i, config.fmtV13), |
- data: data |
- }); |
- var textMeasurement = ctx.measureText(dispString).width; |
- var MaxRadiusX = Math.abs((msr.availableWidth / 2 - textMeasurement) / Math.cos(posAngle)) - config.inGraphDataPaddingRadius - 5; |
- if (MaxRadiusX < doughnutRadius) doughnutRadius = MaxRadiusX; |
- } |
- } |
- } |
- doughnutRadius = doughnutRadius * config.radiusScale; |
- }; |
- }; |
- var Line = function(data, config, ctx) { |
- var maxSize, scaleHop, scaleHop2, calculatedScale, calculatedScale2, labelHeight, scaleHeight, valueBounds, labelTemplateString, labelTemplateString2; |
- var valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, rotateLabels = 0, |
- msr; |
- var zeroY = 0; |
- var zeroY2 = 0; |
- var offsets = []; |
- ctx.tpchart="Line"; |
- setting_new_chart_vars(ctx); |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- // adapt data when length is 1; |
- var mxlgt = 0; |
- for (var i = 0; i < data.datasets.length; i++) mxlgt = Max([mxlgt, data.datasets[i].data.length]); |
- if (mxlgt == 1) { |
- if (typeof(data.labels[0]) == "string") data.labels = ["", data.labels[0], ""]; |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (typeof(data.datasets[i].data[0] != "undefined")) data.datasets[i].data = [undefined, data.datasets[i].data[0], undefined]; |
- } |
- } |
- |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- defMouse(ctx, data, config); |
- setRect(ctx, config); |
- msr = setMeasures(data, config, ctx, height, width, "nihil", [""], false, false, true, true, config.datasetFill, "Line"); |
- valueBounds = getValueBounds(); |
- // true or fuzzy (error for negativ values (included 0)) |
- if (config.logarithmic !== false) { |
- if (valueBounds.minValue <= 0) { |
- config.logarithmic = false; |
- } |
- } |
- if (config.logarithmic2 !== false) { |
- if (valueBounds.minValue2 <= 0) { |
- config.logarithmic2 = false; |
- } |
- } |
- // Check if logarithmic is meanigful |
- var OrderOfMagnitude = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue))); |
- if ((config.logarithmic == 'fuzzy' && OrderOfMagnitude < 4) || config.scaleOverride) { |
- config.logarithmic = false; |
- } |
- // Check if logarithmic is meanigful |
- var OrderOfMagnitude2 = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue2) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue2))); |
- if ((config.logarithmic2 == 'fuzzy' && OrderOfMagnitude2 < 4) || config.scaleOverride2) { |
- config.logarithmic2 = false; |
- } |
- //Check and set the scale |
- labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : ""; |
- labelTemplateString2 = (config.scaleShowLabels2) ? config.scaleLabel2 : ""; |
- if (!config.scaleOverride) { |
- if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) { |
- calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString); |
- } |
- } else { |
- calculatedScale = { |
- steps: config.scaleSteps, |
- stepValue: config.scaleStepWidth, |
- graphMin: config.scaleStartValue, |
- graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth, |
- labels: [] |
- } |
- populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth); |
- } |
- |
- if (valueBounds.dbAxis) { |
- if (!config.scaleOverride2) { |
- if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) { |
- calculatedScale2 = calculateScale(2, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue2, valueBounds.minValue2, labelTemplateString); |
- } |
- } else { |
- calculatedScale2 = { |
- steps: config.scaleSteps2, |
- stepValue: config.scaleStepWidth2, |
- graphMin: config.scaleStartValue2, |
- graphMax: config.scaleStartValue2 + config.scaleSteps2 * config.scaleStepWidth2, |
- labels: [] |
- } |
- populateLabels(2, config, labelTemplateString2, calculatedScale2.labels, calculatedScale2.steps, config.scaleStartValue2, calculatedScale2.graphMax, config.scaleStepWidth2); |
- } |
- } else { |
- calculatedScale2 = { |
- steps: 0, |
- stepValue: 0, |
- graphMin: 0, |
- graphMax: 0, |
- labels: null |
- } |
- } |
- if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) { |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, calculatedScale2.labels, false, false, true, true, config.datasetFill, "Line"); |
- var prevHeight=msr.availableHeight; |
- msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop; |
- msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight; |
- scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps); |
- scaleHop2 = Math.floor(msr.availableHeight / calculatedScale2.steps); |
- valueHop = Math.floor(msr.availableWidth / (data.labels.length - 1)); |
- if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / (data.labels.length - 1)); |
- msr.clrwidth = msr.clrwidth - (msr.availableWidth - (data.labels.length - 1) * valueHop); |
- msr.availableWidth = (data.labels.length - 1) * valueHop; |
- msr.availableHeight = (calculatedScale.steps) * scaleHop; |
- msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight)); |
- msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight)); |
- yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft; |
- xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop; |
- drawLabels(); |
- if (valueBounds.minValue < 0) { |
- zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, scaleHop); |
- } |
- if (valueBounds.minValue2 < 0) { |
- zeroY2 = calculateOffset(config.logarithmic2, 0, calculatedScale2, scaleHop2); |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- offsets[i] = []; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (data.datasets[i].axis == 2) { |
- offsets[i][j] = (calculateOffset(config.logarithmic2, data.datasets[i].data[j], calculatedScale2, scaleHop2) - zeroY2); |
- } else { |
- offsets[i][j] = (calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop) - zeroY); |
- } |
- } |
- } |
- animationLoop(config, drawScale, drawLines, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data); |
- } else { |
- testRedraw(ctx,data,config); |
- } |
- |
- |
- function drawLines(animPc) { |
- drawLinesDataset(1, animPc, data, config, ctx, offsets, { |
- xAxisPosY: xAxisPosY, |
- yAxisPosX: yAxisPosX, |
- valueHop: valueHop, |
- nbValueHop: data.labels.length - 1, |
- scaleHop: scaleHop, |
- zeroY: zeroY, |
- calculatedScale: calculatedScale, |
- logarithmic: config.logarithmic |
- }); |
- drawLinesDataset(2, animPc, data, config, ctx, offsets, { |
- xAxisPosY: xAxisPosY, |
- yAxisPosX: yAxisPosX, |
- valueHop: valueHop, |
- nbValueHop: data.labels.length - 1, |
- scaleHop: scaleHop2, |
- zeroY: zeroY2, |
- calculatedScale: calculatedScale2, |
- logarithmic: config.logarithmic2 |
- }); |
- |
- |
- if (animPc >= 1) { |
- if (typeof drawMath == "function") { |
- drawMath(ctx, config, data, msr, { |
- xAxisPosY: xAxisPosY, |
- yAxisPosX: yAxisPosX, |
- valueHop: valueHop, |
- scaleHop: scaleHop, |
- zeroY: zeroY, |
- calculatedScale: calculatedScale, |
- calculateOffset: calculateOffset |
- }); |
- } |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Line"); |
- }; |
- |
- function drawScale() { |
- //X axis line |
- // if the xScale should be drawn |
- if (config.drawXScaleLine !== false) { |
- for (var s = 0; s < config.drawXScaleLine.length; s++) { |
- // get special lineWidth and lineColor for this xScaleLine |
- ctx.lineWidth = config.drawXScaleLine[s].lineWidth ? config.drawXScaleLine[s].lineWidth : config.scaleLineWidth; |
- ctx.strokeStyle = config.drawXScaleLine[s].lineColor ? config.drawXScaleLine[s].lineColor : config.scaleLineColor; |
- ctx.beginPath(); |
- var yPosXScale; |
- switch (config.drawXScaleLine[s].position) { |
- case "bottom": |
- yPosXScale = xAxisPosY; |
- break; |
- case "top": |
- yPosXScale = xAxisPosY - msr.availableHeight - config.scaleTickSizeTop; |
- break; |
- case "0": |
- case 0: |
- // check if zero exists |
- if (zeroY != 0) { |
- yPosXScale = xAxisPosY - zeroY; |
- } |
- break; |
- } |
- // draw the scale line |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, yPosXScale); |
- ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, yPosXScale); |
- ctx.stroke(); |
- } |
- } |
- for (var i = 0; i < data.labels.length; i++) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- //Check i isnt 0, so we dont go over the Y axis twice. |
- if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- } else { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY); |
- } |
- ctx.stroke(); |
- } |
- //Y axis |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- ctx.stroke(); |
- for (var j = 0; j < calculatedScale.steps; j++) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop)); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop)); |
- } else { |
- ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop)); |
- } |
- ctx.stroke(); |
- } |
- }; |
- |
- function drawLabels() { |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- //X Labels |
- if (config.xAxisTop || config.xAxisBottom) { |
- ctx.textBaseline = "top"; |
- if (msr.rotateLabels > 90) { |
- ctx.save(); |
- ctx.textAlign = "left"; |
- } else if (msr.rotateLabels > 0) { |
- ctx.save(); |
- ctx.textAlign = "right"; |
- } else { |
- ctx.textAlign = "center"; |
- } |
- ctx.fillStyle = config.scaleFontColor; |
- if (config.xAxisBottom) { |
- for (var i = 0; i < data.labels.length; i++) { |
- ctx.save(); |
- if (msr.rotateLabels > 0) { |
- ctx.translate(yAxisPosX + i * valueHop - msr.highestXLabel / 2, msr.xLabelPos); |
- ctx.rotate(-(msr.rotateLabels * (Math.PI / 180))); |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize); |
- } else { |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + i * valueHop, msr.xLabelPos, ctx.textBaseline, config.scaleFontSize); |
- } |
- ctx.restore(); |
- } |
- } |
- } |
- //Y Labels |
- ctx.textAlign = "right"; |
- ctx.textBaseline = "middle"; |
- for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) { |
- if (config.scaleShowLabels) { |
- if (config.yAxisLeft) { |
- ctx.textAlign = "right"; |
- ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize); |
- } |
- if (config.yAxisRight && !valueBounds.dbAxis) { |
- ctx.textAlign = "left"; |
- ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize); |
- } |
- } |
- } |
- if (config.yAxisRight && valueBounds.dbAxis) { |
- for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale2.steps; j++) { |
- if (config.scaleShowLabels) { |
- ctx.textAlign = "left"; |
- ctx.fillTextMultiLine(calculatedScale2.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop2), ctx.textBaseline, config.scaleFontSize); |
- } |
- } |
- } |
- }; |
- |
- function getValueBounds() { |
- var upperValue = Number.MIN_VALUE; |
- var lowerValue = Number.MAX_VALUE; |
- var upperValue2 = Number.MIN_VALUE; |
- var lowerValue2 = Number.MAX_VALUE; |
- var secondAxis = false; |
- var firstAxis = false; |
- for (var i = 0; i < data.datasets.length; i++) { |
- var mathFctName = data.datasets[i].drawMathDeviation; |
- var mathValueHeight = 0; |
- if (typeof eval(mathFctName) == "function") { |
- var parameter = { |
- data: data, |
- datasetNr: i |
- }; |
- mathValueHeight = window[mathFctName](parameter); |
- } |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (data.datasets[i].axis == 2) { |
- secondAxis = true; |
- if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue2) { |
- upperValue2 = 1 * data.datasets[i].data[j] + mathValueHeight |
- }; |
- if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue2) { |
- lowerValue2 = 1 * data.datasets[i].data[j] - mathValueHeight |
- }; |
- } else { |
- firstAxis = true; |
- if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue) { |
- upperValue = 1 * data.datasets[i].data[j] + mathValueHeight |
- }; |
- if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue) { |
- lowerValue = 1 * data.datasets[i].data[j] - mathValueHeight |
- }; |
- } |
- } |
- }; |
- if (Math.abs(upperValue - lowerValue) < 0.00000001) { |
- upperValue = Max([upperValue * 2, 1]); |
- lowerValue = 0; |
- } |
- if (!isNaN(config.graphMin)) lowerValue = config.graphMin; |
- if (!isNaN(config.graphMax)) upperValue = config.graphMax; |
- if (secondAxis) { |
- if (Math.abs(upperValue2 - lowerValue2) < 0.00000001) { |
- upperValue2 = Max([upperValue2 * 2, 1]); |
- lowerValue2 = 0; |
- } |
- if (!isNaN(config.graphMin2)) lowerValue2 = config.graphMin2; |
- if (!isNaN(config.graphMax2)) upperValue2 = config.graphMax2; |
- } |
- if (!firstAxis && secondAxis) { |
- upperValue = upperValue2; |
- lowerValue = lowerValue2; |
- } |
- labelHeight = config.scaleFontSize; |
- scaleHeight = msr.availableHeight; |
- var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66))); |
- var minSteps = Math.floor((scaleHeight / labelHeight * 0.5)); |
- return { |
- maxValue: upperValue, |
- minValue: lowerValue, |
- maxValue2: upperValue2, |
- minValue2: lowerValue2, |
- dbAxis: secondAxis, |
- maxSteps: maxSteps, |
- minSteps: minSteps |
- }; |
- }; |
- }; |
- var StackedBar = function(data, config, ctx) { |
- var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0, |
- msr; |
- ctx.tpchart="StackedBar"; |
- setting_new_chart_vars(ctx); |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- config.logarithmic = false; |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- defMouse(ctx, data, config); |
- setRect(ctx, config); |
- msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, false, true, true, true, "StackedBar"); |
- valueBounds = getValueBounds(); |
- |
- if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) { |
- //Check and set the scale |
- labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : ""; |
- if (!config.scaleOverride) { |
- calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "StackedBar"); |
- } else { |
- calculatedScale = { |
- steps: config.scaleSteps, |
- stepValue: config.scaleStepWidth, |
- graphMin: config.scaleStartValue, |
- labels: [] |
- } |
- for (var i = 0; i <= calculatedScale.steps; i++) { |
- if (labelTemplateString) { |
- calculatedScale.labels.push(tmpl(labelTemplateString, { |
- value: fmtChartJS(config, 1 * ((config.scaleStartValue + (config.scaleStepWidth * i)).toFixed(getDecimalPlaces(config.scaleStepWidth))), config.fmtYLabel) |
- })); |
- } |
- } |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "StackedBar"); |
- } |
- |
- var prevHeight=msr.availableHeight; |
- |
- msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop; |
- msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight; |
- scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps); |
- valueHop = Math.floor(msr.availableWidth / (data.labels.length)); |
- if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / data.labels.length); |
- msr.clrwidth = msr.clrwidth - (msr.availableWidth - ((data.labels.length) * valueHop)); |
- msr.availableWidth = (data.labels.length) * valueHop; |
- msr.availableHeight = (calculatedScale.steps) * scaleHop; |
- msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight)); |
- msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight)); |
- |
- yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft; |
- xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop; |
- barWidth = (valueHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - (config.barStrokeWidth / 2) - 1); |
- if(barWidth>=0 && barWidth<=1)barWidth=1; |
- if(barWidth<0 && barWidth>=-1)barWidth=-1; |
- |
- drawLabels(); |
- animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data); |
- } else { |
- testRedraw(ctx,data,config); |
- } |
- function drawBars(animPc) { |
- ctx.lineWidth = config.barStrokeWidth; |
- var tempp = new Array(data.datasets.length); |
- var tempn = new Array(data.datasets.length); |
- var cumvalue = new Array(); |
- var totvalue = new Array(); |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- cumvalue[j] = 0; |
- totvalue[j] = 0; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- totvalue[j] += 1 * data.datasets[i].data[j]; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (animPc >= 1) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- } |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal; |
- if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1; |
- if (i == 0) { |
- tempp[j]=0; |
- tempn[j]=0; |
- zeroY= calculateOffset(config.logarithmic, 0 , calculatedScale, scaleHop); |
- } |
- var barOffset = yAxisPosX + config.barValueSpacing + valueHop * j; |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined') && 1*data.datasets[i].data[j] != 0 ) { |
- if (1*data.datasets[i].data[j]<0) { |
- var botval=tempp[j]; |
- var topval=tempp[j]+1*data.datasets[i].data[j] ; |
- } else { |
- var botval=tempn[j]; |
- var topval=tempn[j]+1*data.datasets[i].data[j] ; |
- } |
- if(config.animationByDataset) { |
- var botBar=xAxisPosY - calculateOffset(config.logarithmic, botval , calculatedScale, scaleHop); |
- var topBar=xAxisPosY - calculateOffset(config.logarithmic, topval , calculatedScale, scaleHop); |
- topBar=botBar+currentAnimPc*(topBar-botBar); |
- } else { |
- var botBar=xAxisPosY - calculateOffset(config.logarithmic, currentAnimPc* botval , calculatedScale, scaleHop); |
- var topBar=xAxisPosY - calculateOffset(config.logarithmic, currentAnimPc*topval , calculatedScale, scaleHop); |
- |
- } |
- ctx.fillStyle = config.defaultFillColor; |
- if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "StackedBar", ctx, barOffset, botBar , barOffset + barWidth, topBar); |
- else if (typeof(data.datasets[i].fillColor) == "string") { |
- ctx.fillStyle = data.datasets[i].fillColor; |
- } else if (typeof(data.datasets[i].fillColor) == "object") { |
- if (typeof(data.datasets[i].fillColor[0]) == "string") { |
- ctx.fillStyle = data.datasets[i].fillColor[Min([data.datasets[i].fillColor.length - 1, j])]; |
- } |
- } |
- ctx.strokeStyle = config.defaultStrokeColor; |
- if (typeof data.datasets[i].strokeColor == "function") ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "StackedBar", ctx, barOffset, botBar, barOffset + barwidth, topBar); |
- else if (typeof(data.datasets[i].strokeColor) == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor; |
- } else if (typeof(data.datasets[i].strokeColor) == "object") { |
- if (typeof(data.datasets[i].strokeColor[0]) == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor[Min([data.datasets[i].strokeColor.length - 1, j])]; |
- } |
- } |
- |
- if(currentAnimPc !=0) { |
- ctx.beginPath(); |
- ctx.moveTo(barOffset, botBar); |
- ctx.lineTo(barOffset, topBar); |
- ctx.lineTo(barOffset + barWidth, topBar); |
- ctx.lineTo(barOffset + barWidth, botBar); |
- if (config.barShowStroke) ctx.stroke(); |
- ctx.closePath(); |
- ctx.fill(); |
- cumvalue[j] += 1 * data.datasets[i].data[j]; |
- if (animPc >= 1) { |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- else lgtxt2 = ""; |
-// jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", barOffset, xAxisPosY - yStart[j] + 1, barOffset + barWidth, barheight , lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j]; |
- if (1*data.datasets[i].data[j]<0) { |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", barOffset, topBar, barOffset + barWidth, botBar , lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j]; |
- } else { |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", barOffset, botBar, barOffset + barWidth, topBar , lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j]; |
- } |
- } |
- } |
- if (1*data.datasets[i].data[j]<0) { |
- tempp[j]=tempp[j]+1*data.datasets[i].data[j] ; |
- } else { |
- tempn[j]=tempn[j]+1*data.datasets[i].data[j] ; |
- } |
- } |
- } |
- } |
- if (animPc >= 1 && config.inGraphDataShow) { |
- var yPos = 0, |
- xPos = 0; |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- cumvalue[j] = 0; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (i == 0) { |
- tempp[j]=0; |
- tempn[j]=0; |
- zeroY= calculateOffset(config.logarithmic, 0 , calculatedScale, scaleHop); |
- } |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- if (1*data.datasets[i].data[j]<0) { |
- var botval=tempp[j]; |
- var topval=tempp[j]+1*data.datasets[i].data[j] ; |
- } else { |
- var botval=tempn[j]; |
- var topval=tempn[j]+1*data.datasets[i].data[j] ; |
- } |
- var botBar=xAxisPosY - calculateOffset(config.logarithmic, botval , calculatedScale, scaleHop); |
- var topBar=xAxisPosY - calculateOffset(config.logarithmic, topval , calculatedScale, scaleHop); |
- ctx.save(); |
- ctx.textAlign = config.inGraphDataAlign; |
- ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- else lgtxt2 = ""; |
- cumvalue[j] += 1 + data.datasets[i].data[j]; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, lgtxt2, config.fmtV2), |
- v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3), |
- v4: fmtChartJS(config, cumvalue[j], config.fmtV4), |
- v5: fmtChartJS(config, totvalue[j], config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, barOffset, config.fmtV7), |
- v8: fmtChartJS(config, xAxisPosY, config.fmtV8), |
- v9: fmtChartJS(config, barOffset + barWidth, config.fmtV9), |
- v10: fmtChartJS(config, xAxisPosY - calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop) + (config.barStrokeWidth / 2), config.fmtV10), |
- v11: fmtChartJS(config, i, config.fmtV11), |
- v12: fmtChartJS(config, j, config.fmtV12), |
- data: data |
- }); |
- var barOffset = yAxisPosX + config.barValueSpacing + valueHop * j; |
- ctx.beginPath(); |
- ctx.beginPath(); |
- yPos = 0; |
- xPos = 0; |
- if (config.inGraphDataXPosition == 1) { |
- xPos = barOffset + config.inGraphDataPaddingX; |
- } else if (config.inGraphDataXPosition == 2) { |
- xPos = barOffset + barWidth / 2 + config.inGraphDataPaddingX; |
- } else if (config.inGraphDataXPosition == 3) { |
- xPos = barOffset + barWidth + config.inGraphDataPaddingX; |
- } |
- if (config.inGraphDataYPosition == 1) { |
- yPos = botBar - config.inGraphDataPaddingY; |
- } else if (config.inGraphDataYPosition == 2) { |
- yPos = topBar - (botbar-topbar)/2 - config.inGraphDataPaddingY; |
- } else if (config.inGraphDataYPosition == 3) { |
- yPos = topBar - config.inGraphDataPaddingY; |
- } |
- if(yPos>msr.topNotUsableSize) { |
- ctx.translate(xPos, yPos); |
- ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- } |
- ctx.restore(); |
- if (1*data.datasets[i].data[j]<0) { |
- tempp[j]=tempp[j]+1*data.datasets[i].data[j] ; |
- } else { |
- tempn[j]=tempn[j]+1*data.datasets[i].data[j] ; |
- } |
- } |
- } |
- } |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"StackedBar"); |
- }; |
- |
- function drawScale() { |
- //X axis line |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY); |
- ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY); |
- ctx.stroke(); |
- for (var i = 0; i < data.labels.length; i++) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- //Check i isnt 0, so we dont go over the Y axis twice. |
- if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- } else { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY); |
- } |
- ctx.stroke(); |
- } |
- //Y axis |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- ctx.stroke(); |
- for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop)); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop)); |
- } else { |
- ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop)); |
- } |
- ctx.stroke(); |
- } |
- }; |
- |
- function drawLabels() { |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- //X axis labels |
- if (config.xAxisTop || config.xAxisBottom) { |
- ctx.textBaseline = "top"; |
- if (msr.rotateLabels > 90) { |
- ctx.save(); |
- ctx.textAlign = "left"; |
- } else if (msr.rotateLabels > 0) { |
- ctx.save(); |
- ctx.textAlign = "right"; |
- } else { |
- ctx.textAlign = "center"; |
- } |
- ctx.fillStyle = config.scaleFontColor; |
- if (config.xAxisBottom) { |
- for (var i = 0; i < data.labels.length; i++) { |
- ctx.save(); |
- if (msr.rotateLabels > 0) { |
- ctx.translate(yAxisPosX + i * valueHop + (barWidth / 2) - msr.highestXLabel / 2, msr.xLabelPos); |
- ctx.rotate(-(msr.rotateLabels * (Math.PI / 180))); |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize); |
- } else { |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + i * valueHop + (barWidth / 2), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize); |
- } |
- ctx.restore(); |
- } |
- } |
- } |
- //Y axis |
- ctx.textAlign = "right"; |
- ctx.textBaseline = "middle"; |
- for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) { |
- if (config.scaleShowLabels) { |
- if (config.yAxisLeft) { |
- ctx.textAlign = "right"; |
- ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize); |
- } |
- if (config.yAxisRight) { |
- ctx.textAlign = "left"; |
- ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize); |
- } |
- } |
- } |
- }; |
- |
- function getValueBounds() { |
- var upperValue = Number.MIN_VALUE; |
- var lowerValue = Number.MAX_VALUE; |
- var minvl = new Array(data.datasets.length); |
- var maxvl = new Array(data.datasets.length); |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- var k = i; |
- var tempp = 0; |
- var tempn = 0; |
- if (!(typeof(data.datasets[0].data[j]) == 'undefined')) { |
- if(1 * data.datasets[0].data[j] > 0) { |
- tempp += 1 * data.datasets[0].data[j]; |
- if (tempp > upperValue) { |
- upperValue = tempp; |
- }; |
- if (tempp < lowerValue) { |
- lowerValue = tempp; |
- }; |
- } else { |
- tempn += 1 * data.datasets[0].data[j]; |
- if (tempn > upperValue) { |
- upperValue = tempn; |
- }; |
- if (tempn < lowerValue) { |
- lowerValue = tempn; |
- }; |
- } |
- } |
- while (k > 0) { //get max of stacked data |
- if (!(typeof(data.datasets[k].data[j]) == 'undefined')) { |
- if(1 * data.datasets[k].data[j] > 0) { |
- tempp += 1 * data.datasets[k].data[j]; |
- if (tempp > upperValue) { |
- upperValue = tempp; |
- }; |
- if (tempp < lowerValue) { |
- lowerValue = tempp; |
- }; |
- } else { |
- tempn += 1 * data.datasets[k].data[j]; |
- if (tempn > upperValue) { |
- upperValue = tempn; |
- }; |
- if (tempn < lowerValue) { |
- lowerValue = tempn; |
- }; |
- } |
- } |
- k--; |
- } |
- } |
- }; |
- // AJOUT CHANGEMENT |
- |
- if (!isNaN(config.graphMin)) lowerValue = config.graphMin; |
- if (!isNaN(config.graphMax)) upperValue = config.graphMax; |
- if (Math.abs(upperValue - lowerValue) < 0.00000001) { |
- upperValue = Max([upperValue * 2, 1]); |
- lowerValue = 0; |
- } |
- labelHeight = config.scaleFontSize; |
- scaleHeight = msr.availableHeight; |
- var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66))); |
- var minSteps = Math.floor((scaleHeight / labelHeight * 0.5)); |
- return { |
- maxValue: upperValue, |
- minValue: lowerValue, |
- maxSteps: maxSteps, |
- minSteps: minSteps |
- }; |
- }; |
- }; |
- /** |
- * Reverse the data structure for horizontal charts |
- * - reverse labels and every array inside datasets |
- * @param {object} data datasets and labels for the chart |
- * @return return the reversed data |
- */ |
- function reverseData(data) { |
- data.labels = data.labels.reverse(); |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var key in data.datasets[i]) { |
- if (Array.isArray(data.datasets[i][key])) { |
- data.datasets[i][key] = data.datasets[i][key].reverse(); |
- } |
- } |
- } |
- return data; |
- } |
- var HorizontalStackedBar = function(data, config, ctx) { |
- var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0, |
- msr; |
- |
- ctx.tpchart="HorizontalStackedBar"; |
- setting_new_chart_vars(ctx); |
- |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- if (config.reverseOrder && typeof ctx.reversed == "undefined") { |
- ctx.reversed=true; |
- data = reverseData(data); |
- } |
- |
- |
- config.logarithmic = false; |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- defMouse(ctx, data, config); |
- setRect(ctx, config); |
- msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, true, true, true, true, "HorizontalStackedBar"); |
- valueBounds = getValueBounds(); |
- |
- if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) { |
- //Check and set the scale |
- labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : ""; |
- if (!config.scaleOverride) { |
- calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalStackedBar"); |
- } else { |
- calculatedScale = { |
- steps: config.scaleSteps, |
- stepValue: config.scaleStepWidth, |
- graphMin: config.scaleStartValue, |
- labels: [] |
- } |
- for (var i = 0; i <= calculatedScale.steps; i++) { |
- if (labelTemplateString) { |
- calculatedScale.labels.push(tmpl(labelTemplateString, { |
- value: fmtChartJS(config, 1 * ((config.scaleStartValue + (config.scaleStepWidth * i)).toFixed(getDecimalPlaces(config.scaleStepWidth))), config.fmtYLabel) |
- })); |
- } |
- } |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalStackedBar"); |
- } |
- msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop; |
- msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight; |
- scaleHop = Math.floor(msr.availableHeight / data.labels.length); |
- valueHop = Math.floor(msr.availableWidth / (calculatedScale.steps)); |
- if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / (calculatedScale.steps)); |
- msr.clrwidth = msr.clrwidth - (msr.availableWidth - (calculatedScale.steps * valueHop)); |
- msr.availableWidth = (calculatedScale.steps) * valueHop; |
- msr.availableHeight = (data.labels.length) * scaleHop; |
- yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft; |
- xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop; |
- barWidth = (scaleHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - (config.barStrokeWidth / 2) - 1); |
- if(barWidth>=0 && barWidth<=1)barWidth=1; |
- if(barWidth<0 && barWidth>=-1)barWidth=-1; |
- drawLabels(); |
- animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data); |
- } else { |
- testRedraw(ctx,data,config); |
- } |
- function HorizontalCalculateOffset(val, calculatedScale, scaleHop) { |
- var outerValue = calculatedScale.steps * calculatedScale.stepValue; |
- var adjustedValue = val - calculatedScale.graphMin; |
- var scalingFactor = CapValue(adjustedValue / outerValue, 1, 0); |
- return (scaleHop * calculatedScale.steps) * scalingFactor; |
- }; |
- |
- function drawBars(animPc) { |
- ctx.lineWidth = config.barStrokeWidth; |
- var tempp = new Array(data.datasets.length); |
- var tempn = new Array(data.datasets.length); |
- var cumvalue = new Array(); |
- var totvalue = new Array(); |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- cumvalue[j] = 0; |
- totvalue[j] = 0; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- totvalue[j] += 1 * data.datasets[i].data[j]; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (animPc >= 1) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- } |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal; |
- if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1; |
- if (i == 0) { |
- tempp[j]=0; |
- tempn[j]=0; |
- zeroY= HorizontalCalculateOffset(0 , calculatedScale, scaleHop); |
- } |
- var barOffset = xAxisPosY + config.barValueSpacing - scaleHop * (j + 1); |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined') && 1*data.datasets[i].data[j] != 0 ) { |
- if (1*data.datasets[i].data[j]<0) { |
- var botval=tempp[j]; |
- var topval=tempp[j]+1*data.datasets[i].data[j] ; |
- } else { |
- var botval=tempn[j]; |
- var topval=tempn[j]+1*data.datasets[i].data[j] ; |
- } |
- if(config.animationByDataset) { |
- var botBar=yAxisPosX + HorizontalCalculateOffset(botval , calculatedScale, valueHop); |
- var topBar=yAxisPosX + HorizontalCalculateOffset(topval , calculatedScale, valueHop); |
- topBar=botBar+currentAnimPc*(topBar-botBar); |
- } else { |
- var botBar=yAxisPosX + HorizontalCalculateOffset( currentAnimPc* botval , calculatedScale, valueHop); |
- var topBar=yAxisPosX + HorizontalCalculateOffset( currentAnimPc*topval , calculatedScale, valueHop); |
- |
- } |
- ctx.fillStyle = config.defaultFillColor; |
- if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "HorizontalStackedBar", ctx, botBar, barOffset, topBar, barOffset + barWidth); |
- else if (typeof(data.datasets[i].fillColor) == "string") { |
- ctx.fillStyle = data.datasets[i].fillColor; |
- } else if (typeof(data.datasets[i].fillColor) == "object") { |
- if (typeof(data.datasets[i].fillColor[0]) == "string") { |
- ctx.fillStyle = data.datasets[i].fillColor[Min([data.datasets[i].fillColor.length - 1, j])]; |
- } |
- } |
- ctx.strokeStyle = config.defaultStrokeColor; |
- if (typeof data.datasets[i].strokeColor == "function") ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], ctx, "HorizontalStackedBar", ctx, botBar, barOffset, topBar, barOffset + barWidth); |
- else if (typeof(data.datasets[i].strokeColor) == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor; |
- } else if (typeof(data.datasets[i].strokeColor) == "object") { |
- if (typeof(data.datasets[i].strokeColor[0]) == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor[Min([data.datasets[i].strokeColor.length - 1, j])]; |
- } |
- } |
- if(currentAnimPc !=0) { |
- ctx.beginPath(); |
- ctx.moveTo(botBar, barOffset); |
- ctx.lineTo(topBar, barOffset); |
- ctx.lineTo(topBar, barOffset + barWidth); |
- ctx.lineTo(botBar, barOffset + barWidth); |
- ctx.lineTo(botBar, barOffset); |
- if (config.barShowStroke) ctx.stroke(); |
- ctx.closePath(); |
- ctx.fill(); |
- cumvalue[j] += 1 * data.datasets[i].data[j]; |
- if (animPc >= 1) { |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- else lgtxt2 = ""; |
- if (1*data.datasets[i].data[j]<0) { |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", topBar, barOffset + barWidth, botBar, barOffset, lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j]; |
- } else { |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", botBar, barOffset + barWidth, topBar, barOffset, lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j]; |
- } |
- } |
- } |
- if (1*data.datasets[i].data[j]<0) { |
- tempp[j]=tempp[j]+1*data.datasets[i].data[j] ; |
- } else { |
- tempn[j]=tempn[j]+1*data.datasets[i].data[j] ; |
- } |
- } |
- } |
- } |
- if (animPc >= 1 && config.inGraphDataShow) { |
- var yPos = 0, |
- xPos = 0; |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- cumvalue[j] = 0; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (i == 0) { |
- tempp[j]=0; |
- tempn[j]=0; |
- zeroY= HorizontalCalculateOffset(0 , calculatedScale, scaleHop); |
- } |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- if (1*data.datasets[i].data[j]<0) { |
- var botval=tempp[j]; |
- var topval=tempp[j]+1*data.datasets[i].data[j] ; |
- } else { |
- var botval=tempn[j]; |
- var topval=tempn[j]+1*data.datasets[i].data[j] ; |
- } |
- var botBar=yAxisPosX + HorizontalCalculateOffset(botval , calculatedScale, valueHop); |
- var topBar=yAxisPosX + HorizontalCalculateOffset(topval , calculatedScale, valueHop); |
- ctx.save(); |
- ctx.textAlign = config.inGraphDataAlign; |
- ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- else lgtxt2 = ""; |
- var barOffset = xAxisPosY + config.barValueSpacing - scaleHop * (j + 1); |
- cumvalue[j] += data.datasets[i].data[j]; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, lgtxt2, config.fmtV2), |
- v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3), |
- v4: fmtChartJS(config, cumvalue[j], config.fmtV4), |
- v5: fmtChartJS(config, totvalue[j], config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, yAxisPosX, config.fmtV7), |
- v8: fmtChartJS(config, barOffset + barWidth, config.fmtV8), |
- v9: fmtChartJS(config, yAxisPosX + HorizontalCalculateOffset(data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2), config.fmtV9), |
- v10: fmtChartJS(config, barOffset, config.fmtV10), |
- v11: fmtChartJS(config, i, config.fmtV11), |
- v12: fmtChartJS(config, j, config.fmtV12), |
- data: data |
- }); |
- ctx.beginPath(); |
- yPos = 0; |
- xPos = 0; |
- if (config.inGraphDataXPosition == 1) { |
- xPos = botBar + config.inGraphDataPaddingX; |
- } else if (config.inGraphDataXPosition == 2) { |
- xPos = botBar + (topBar-botBar)/2 + config.inGraphDataPaddingX; |
- } else if (config.inGraphDataXPosition == 3) { |
- xPos = topBar + config.inGraphDataPaddingX; |
- } |
- if (config.inGraphDataYPosition == 1) { |
- yPos = barOffset + barWidth - config.inGraphDataPaddingY; |
- } else if (config.inGraphDataYPosition == 2) { |
- yPos = barOffset + barWidth / 2 - config.inGraphDataPaddingY; |
- } else if (config.inGraphDataYPosition == 3) { |
- yPos = barOffset - config.inGraphDataPaddingY; |
- } |
- if(xPos<=msr.availableWidth+msr.leftNotUsableSize) { |
- ctx.translate(xPos, yPos); |
- ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- ctx.restore(); |
- } |
- if (1*data.datasets[i].data[j]<0) { |
- tempp[j]=tempp[j]+1*data.datasets[i].data[j] ; |
- } else { |
- tempn[j]=tempn[j]+1*data.datasets[i].data[j] ; |
- } |
- } |
- } |
- } |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"HorizontalStackedBar"); |
- }; |
- |
- function drawScale() { |
- //X axis line |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY); |
- ctx.lineTo(yAxisPosX + msr.availableWidth, xAxisPosY); |
- ctx.stroke(); |
- for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) { |
- if (i >= 0) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- //Check i isnt 0, so we dont go over the Y axis twice. |
- if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- } else { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY); |
- } |
- ctx.stroke(); |
- } |
- } |
- //Y axis |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- ctx.stroke(); |
- for (var j = 0; j < data.labels.length; j++) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop)); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + msr.availableWidth, xAxisPosY - ((j + 1) * scaleHop)); |
- } else { |
- ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop)); |
- } |
- ctx.stroke(); |
- } |
- }; |
- |
- function drawLabels() { |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- //X axis line |
- if (config.scaleShowLabels && (config.xAxisTop || config.xAxisBottom)) { |
- ctx.textBaseline = "top"; |
- if (msr.rotateLabels > 90) { |
- ctx.save(); |
- ctx.textAlign = "left"; |
- } else if (msr.rotateLabels > 0) { |
- ctx.save(); |
- ctx.textAlign = "right"; |
- } else { |
- ctx.textAlign = "center"; |
- } |
- ctx.fillStyle = config.scaleFontColor; |
- if (config.xAxisBottom) { |
- for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) { |
- ctx.save(); |
- if (msr.rotateLabels > 0) { |
- ctx.translate(yAxisPosX + (i + 1) * valueHop - msr.highestXLabel / 2, msr.xLabelPos); |
- ctx.rotate(-(msr.rotateLabels * (Math.PI / 180))); |
- ctx.fillTextMultiLine(calculatedScale.labels[i + 1], 0, 0, ctx.textBaseline, config.scaleFontSize); |
- } else { |
- ctx.fillTextMultiLine(calculatedScale.labels[i + 1], yAxisPosX + ((i + 1) * valueHop), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize); |
- } |
- ctx.restore(); |
- } |
- } |
- } |
- //Y axis |
- ctx.textAlign = "right"; |
- ctx.textBaseline = "middle"; |
- for (var j = 0; j < data.labels.length; j++) { |
- if (config.yAxisLeft) { |
- ctx.textAlign = "right"; |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop) + barWidth / 2, ctx.textBaseline, config.scaleFontSize); |
- } |
- if (config.yAxisRight) { |
- ctx.textAlign = "left"; |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop) + barWidth / 2, ctx.textBaseline, config.scaleFontSize); |
- } |
- } |
- }; |
- |
- function getValueBounds() { |
- var upperValue = Number.MIN_VALUE; |
- var lowerValue = Number.MAX_VALUE; |
- var minvl = new Array(data.datasets.length); |
- var maxvl = new Array(data.datasets.length); |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- var k = i; |
- var tempp = 0; |
- var tempn = 0; |
- if (!(typeof(data.datasets[0].data[j]) == 'undefined')) { |
- if(1 * data.datasets[0].data[j] > 0) { |
- tempp += 1 * data.datasets[0].data[j]; |
- if (tempp > upperValue) { |
- upperValue = tempp; |
- }; |
- if (tempp < lowerValue) { |
- lowerValue = tempp; |
- }; |
- } else { |
- tempn += 1 * data.datasets[0].data[j]; |
- if (tempn > upperValue) { |
- upperValue = tempn; |
- }; |
- if (tempn < lowerValue) { |
- lowerValue = tempn; |
- }; |
- } |
- } |
- while (k > 0) { //get max of stacked data |
- if (!(typeof(data.datasets[k].data[j]) == 'undefined')) { |
- if(1 * data.datasets[k].data[j] > 0) { |
- tempp += 1 * data.datasets[k].data[j]; |
- if (tempp > upperValue) { |
- upperValue = tempp; |
- }; |
- if (tempp < lowerValue) { |
- lowerValue = tempp; |
- }; |
- } else { |
- tempn += 1 * data.datasets[k].data[j]; |
- if (tempn > upperValue) { |
- upperValue = tempn; |
- }; |
- if (tempn < lowerValue) { |
- lowerValue = tempn; |
- }; |
- } |
- } |
- k--; |
- } |
- } |
- }; |
- // AJOUT CHANGEMENT |
- |
- if (!isNaN(config.graphMin)) lowerValue = config.graphMin; |
- if (!isNaN(config.graphMax)) upperValue = config.graphMax; |
- if (Math.abs(upperValue - lowerValue) < 0.00000001) { |
- upperValue = Max([upperValue * 2, 1]); |
- lowerValue = 0; |
- } |
- labelHeight = config.scaleFontSize; |
- scaleHeight = msr.availableHeight; |
- var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66))); |
- var minSteps = Math.floor((scaleHeight / labelHeight * 0.5)); |
- return { |
- maxValue: upperValue, |
- minValue: lowerValue, |
- maxSteps: maxSteps, |
- minSteps: minSteps |
- }; |
- |
- |
- }; |
- }; |
- var Bar = function(data, config, ctx) { |
- var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0, |
- msr; |
- var offsets = []; |
- |
- ctx.tpchart="Bar"; |
- setting_new_chart_vars(ctx); |
- |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- // for BarLineCharts |
- var nrOfBars = data.datasets.length; |
- var nrOfLines = 0; |
- var lineDatasets = []; |
- var barDatasets = []; |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (data.datasets[i].type == "Line") { |
- nrOfLines++; |
- lineDatasets.push(i); |
- } else { |
- barDatasets.push(i); |
- } |
- } |
- // change the order (at first all bars then the lines) (form of BubbleSort) |
- var bufferDataset, l = 0; |
- for (var i = data.datasets.length - 1; i >= 0; i--) { |
- if (lineDatasets.indexOf(i) >= 0) { |
- l++; |
- for (var b = i; b < data.datasets.length - l; b++) { |
- bufferDataset = data.datasets[b + 1]; |
- data.datasets[b + 1] = data.datasets[b]; |
- data.datasets[b] = bufferDataset; |
- } |
- } |
- } |
- nrOfBars -= nrOfLines; |
- |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- defMouse(ctx, data, config); |
- setRect(ctx, config); |
- |
- msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, false, true, true, true, "Bar"); |
- valueBounds = getValueBounds(); |
- |
- if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) { |
- |
- // true or fuzzy (error for negativ values (included 0)) |
- if (config.logarithmic !== false) { |
- if (valueBounds.minValue <= 0) { |
- config.logarithmic = false; |
- } |
- } |
- // Check if logarithmic is meanigful |
- var OrderOfMagnitude = calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.maxValue) + 1)) - calculateOrderOfMagnitude(Math.pow(10, calculateOrderOfMagnitude(valueBounds.minValue))); |
- if ((config.logarithmic == 'fuzzy' && OrderOfMagnitude < 4) || config.scaleOverride) { |
- config.logarithmic = false; |
- } |
- //Check and set the scale |
- labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : ""; |
- if (!config.scaleOverride) { |
- calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "Bar"); |
- } else { |
- calculatedScale = { |
- steps: config.scaleSteps, |
- stepValue: config.scaleStepWidth, |
- graphMin: config.scaleStartValue, |
- graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth, |
- labels: [] |
- } |
- populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, false, true, true, true, "Bar"); |
- } |
- |
- var prevHeight=msr.availableHeight; |
- |
- |
- |
- msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop; |
- msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight; |
- scaleHop = Math.floor(msr.availableHeight / calculatedScale.steps); |
- valueHop = Math.floor(msr.availableWidth / (data.labels.length)); |
- if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / data.labels.length); |
- msr.clrwidth = msr.clrwidth - (msr.availableWidth - ((data.labels.length) * valueHop)); |
- msr.availableWidth = (data.labels.length) * valueHop; |
- msr.availableHeight = (calculatedScale.steps) * scaleHop; |
- msr.xLabelPos+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight)); |
- msr.clrheight+=(config.scaleTickSizeBottom + config.scaleTickSizeTop - (prevHeight-msr.availableHeight)); |
- |
- yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft; |
- xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop; |
- barWidth = (valueHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * nrOfBars - 1) - ((config.barStrokeWidth / 2) * nrOfBars - 1)) / nrOfBars; |
- if(barWidth>=0 && barWidth<=1)barWidth=1; |
- if(barWidth<0 && barWidth>=-1)barWidth=-1; |
- var zeroY = 0; |
- if (valueBounds.minValue < 0) { |
- var zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, scaleHop); |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- offsets[i] = []; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- offsets[i][j] = (calculateOffset(config.logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop) - zeroY); |
- } |
- } |
- drawLabels(); |
- animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data); |
- } else { |
- testRedraw(ctx,data,config); |
- } |
- function drawBars(animPc) { |
- var t1, t2, t3; |
- var cumvalue = new Array(); |
- var totvalue = new Array(); |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- cumvalue[j] = 0; |
- totvalue[j] = 0; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- totvalue[j] += 1 * data.datasets[i].data[j]; |
- } |
- } |
- } |
- ctx.lineWidth = config.barStrokeWidth; |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (data.datasets[i].type == "Line") { |
- var lineData = { |
- datasets: [], |
- labels: data.labels |
- }; |
- lineData.datasets.push(data.datasets[i]); |
- lineConfig = mergeChartConfig(config, { |
- datasetFill: data.datasets[i].fill |
- }); |
- drawLinesDataset(1, animPc, lineData, lineConfig, ctx, offsets, { |
- xAxisPosY: xAxisPosY, |
- yAxisPosX: yAxisPosX + config.barValueSpacing + |
- (barWidth + config.barDatasetSpacing / 2 + config.barStrokeWidth) * nrOfBars / 2, |
- valueHop: valueHop, |
- scaleHop: scaleHop, |
- nbValueHop: data.labels.length, |
- zeroY: zeroY, |
- calculatedScale: calculatedScale, |
- logarithmic: config.logarithmic |
- }); |
- continue; // next dataset |
- } |
- if (animPc >= 1) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- } |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal; |
- if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1; |
- var barOffset = yAxisPosX + config.barValueSpacing + valueHop * j + barWidth * i + config.barDatasetSpacing * i + config.barStrokeWidth * i; |
- var barHeight = currentAnimPc * (calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) - zeroY) + (config.barStrokeWidth / 2); |
- ctx.fillStyle = config.defaultFillColor; |
- if (typeof data.datasets[i].fillColor == "function") { |
- ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "Bar", ctx, barOffset, xAxisPosY - zeroY , barOffset + barWidth, xAxisPosY - zeroY - barHeight); |
- } else if (typeof(data.datasets[i].fillColor) == "string") { |
- ctx.fillStyle = data.datasets[i].fillColor; |
- } else if (typeof(data.datasets[i].fillColor) == "object") { |
- if (typeof(data.datasets[i].fillColor[0]) == "string") { |
- ctx.fillStyle = data.datasets[i].fillColor[Min([data.datasets[i].fillColor.length - 1, j])]; |
- } |
- } |
- ctx.strokeStyle = config.defaultStrokeColor; |
- if (typeof data.datasets[i].strokeColor == "function") { |
- ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, j, CurrentAnimPc, 1 * data.datasets[i].data[j], "Bar", ctx, barOffset, xAxisPosY - zeroY - barHeight, barOffset + barWidth, xAxisPosY - zeroY); |
- } else if (typeof(data.datasets[i].strokeColor) == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor; |
- } else if (typeof(data.datasets[i].strokeColor) == "object") { |
- if (typeof(data.datasets[i].strokeColor[0]) == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor[Min([data.datasets[i].strokeColor.length - 1, j])]; |
- } |
- } |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- roundRect(ctx, barOffset, xAxisPosY - zeroY, barWidth, barHeight, config.barShowStroke, config.barBorderRadius); |
- cumvalue[j] += 1 * data.datasets[i].data[j]; |
- if (animPc >= 1) { |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- else lgtxt2 = ""; |
- t1 = xAxisPosY - zeroY; |
- t2 = xAxisPosY - calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) + (config.barStrokeWidth / 2); |
- if (t1 < t2) { |
- t3 = t1; |
- t1 = t2; |
- t2 = t3 |
- } |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", barOffset, t1, barOffset + barWidth, t2, lgtxt, lgtxt2, |
- 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j |
- ]; |
- } |
- } |
- } |
- } |
- if (animPc >= 1 && config.inGraphDataShow) { |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- cumvalue[j] = 0; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (data.datasets[i].type == "Line") { // no inGraphDataShow for lines again (is inside drawLinesDataset) |
- continue; |
- } |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- ctx.save(); |
- ctx.textAlign = config.inGraphDataAlign; |
- ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- var barOffset = yAxisPosX + config.barValueSpacing + valueHop * j + barWidth * i + config.barDatasetSpacing * i + config.barStrokeWidth * i; |
- t1 = xAxisPosY - zeroY; |
- t2 = xAxisPosY - calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) + (config.barStrokeWidth / 2); |
- ctx.beginPath(); |
- var yPos = 0, |
- xPos = 0; |
- if (config.inGraphDataXPosition == 1) { |
- xPos = barOffset + config.inGraphDataPaddingX; |
- } else if (config.inGraphDataXPosition == 2) { |
- xPos = barOffset + barWidth / 2 + config.inGraphDataPaddingX; |
- } else if (config.inGraphDataXPosition == 3) { |
- xPos = barOffset + barWidth + config.inGraphDataPaddingX; |
- } |
- if (config.inGraphDataYPosition == 1) { |
- yPos = xAxisPosY - zeroY - config.inGraphDataPaddingY; |
- } else if (config.inGraphDataYPosition == 2) { |
- yPos = xAxisPosY - (calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) + |
- (config.barStrokeWidth / 2)) / 2 - config.inGraphDataPaddingY; |
- } else if (config.inGraphDataYPosition == 3) { |
- yPos = xAxisPosY - calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, scaleHop) + |
- (config.barStrokeWidth / 2) - config.inGraphDataPaddingY; |
- } |
- ctx.translate(xPos, yPos); |
- cumvalue[j] += 1 * data.datasets[i].data[j]; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, lgtxt2, config.fmtV2), |
- v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3), |
- v4: fmtChartJS(config, cumvalue[j], config.fmtV4), |
- v5: fmtChartJS(config, totvalue[j], config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, |
- 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, barOffset, config.fmtV7), |
- v8: fmtChartJS(config, t1, config.fmtV8), |
- v9: fmtChartJS(config, barOffset + barWidth, config.fmtV9), |
- v10: fmtChartJS(config, t2, config.fmtV10), |
- v11: fmtChartJS(config, i, config.fmtV11), |
- v12: fmtChartJS(config, j, config.fmtV12), |
- data: data |
- }); |
- ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- ctx.restore(); |
- } |
- } |
- } |
- } |
- if (animPc >= 1) { |
- if (typeof drawMath == "function") { |
- drawMath(ctx, config, data, msr, { |
- xAxisPosY: xAxisPosY, |
- yAxisPosX: yAxisPosX, |
- valueHop: valueHop, |
- scaleHop: scaleHop, |
- zeroY: zeroY, |
- calculatedScale: calculatedScale, |
- calculateOffset: calculateOffset, |
- barWidth: barWidth |
- }); |
- } |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"Bar"); |
- }; |
- |
- function roundRect(ctx, x, y, w, h, stroke, radius) { |
- ctx.beginPath(); |
- ctx.moveTo(x + radius, y); |
- ctx.lineTo(x + w - radius, y); |
- ctx.quadraticCurveTo(x + w, y, x + w, y); |
- ctx.lineTo(x + w, y - h + radius); |
- ctx.quadraticCurveTo(x + w, y - h, x + w - radius, y - h); |
- ctx.lineTo(x + radius, y - h); |
- ctx.quadraticCurveTo(x, y - h, x, y - h + radius); |
- ctx.lineTo(x, y); |
- ctx.quadraticCurveTo(x, y, x + radius, y); |
- if (stroke) ctx.stroke(); |
- ctx.closePath(); |
- ctx.fill(); |
- }; |
- |
- function drawScale() { |
- //X axis line |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- |
- |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY); |
- ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY); |
- ctx.stroke(); |
- for (var i = 0; i < data.labels.length; i++) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- //Check i isnt 0, so we dont go over the Y axis twice. |
- if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- } else { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY); |
- } |
- ctx.stroke(); |
- } |
- //Y axis |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- ctx.stroke(); |
- for (var j = 0; j < calculatedScale.steps; j++) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop)); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop)); |
- } else { |
- ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop)); |
- } |
- ctx.stroke(); |
- } |
- }; |
- |
- function drawLabels() { |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- //X axis line |
- if (config.xAxisTop || config.xAxisBottom) { |
- ctx.textBaseline = "top"; |
- if (msr.rotateLabels > 90) { |
- ctx.save(); |
- ctx.textAlign = "left"; |
- } else if (msr.rotateLabels > 0) { |
- ctx.save(); |
- ctx.textAlign = "right"; |
- } else { |
- ctx.textAlign = "center"; |
- } |
- ctx.fillStyle = config.scaleFontColor; |
- if (config.xAxisBottom) { |
- for (var i = 0; i < data.labels.length; i++) { |
- ctx.save(); |
- if (msr.rotateLabels > 0) { |
- |
- ctx.translate(yAxisPosX + i * valueHop + (valueHop / 2) - msr.highestXLabel / 2, msr.xLabelPos); |
- ctx.rotate(-(msr.rotateLabels * (Math.PI / 180))); |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), 0, 0, ctx.textBaseline, config.scaleFontSize); |
- } else { |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), yAxisPosX + i * valueHop + (valueHop / 2), msr.xLabelPos, ctx.textBaseline, config.scaleFontSize); |
- } |
- ctx.restore(); |
- } |
- } |
- } |
- //Y axis |
- ctx.textAlign = "right"; |
- ctx.textBaseline = "middle"; |
- for (var j = ((config.showYAxisMin) ? -1 : 0); j < calculatedScale.steps; j++) { |
- if (config.scaleShowLabels) { |
- if (config.yAxisLeft) { |
- ctx.textAlign = "right"; |
- ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize); |
- } |
- if (config.yAxisRight) { |
- ctx.textAlign = "left"; |
- ctx.fillTextMultiLine(calculatedScale.labels[j + 1], yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - ((j + 1) * scaleHop), ctx.textBaseline, config.scaleFontSize); |
- } |
- } |
- } |
- }; |
- |
- function getValueBounds() { |
- var upperValue = Number.MIN_VALUE; |
- var lowerValue = Number.MAX_VALUE; |
- for (var i = 0; i < data.datasets.length; i++) { |
- var mathFctName = data.datasets[i].drawMathDeviation; |
- var mathValueHeight = 0; |
- if (typeof eval(mathFctName) == "function") { |
- var parameter = { |
- data: data, |
- datasetNr: i |
- }; |
- mathValueHeight = window[mathFctName](parameter); |
- } |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (1 * data.datasets[i].data[j] + mathValueHeight > upperValue) { |
- upperValue = 1 * data.datasets[i].data[j] + mathValueHeight |
- }; |
- if (1 * data.datasets[i].data[j] - mathValueHeight < lowerValue) { |
- lowerValue = 1 * data.datasets[i].data[j] - mathValueHeight |
- }; |
- } |
- }; |
- if (Math.abs(upperValue - lowerValue) < 0.00000001) { |
- upperValue = Max([upperValue * 2, 1]); |
- lowerValue = 0; |
- } |
- // AJOUT CHANGEMENT |
- if (!isNaN(config.graphMin)) lowerValue = config.graphMin; |
- if (!isNaN(config.graphMax)) upperValue = config.graphMax; |
- labelHeight = config.scaleFontSize; |
- scaleHeight = msr.availableHeight; |
- var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66))); |
- var minSteps = Math.floor((scaleHeight / labelHeight * 0.5)); |
- return { |
- maxValue: upperValue, |
- minValue: lowerValue, |
- maxSteps: maxSteps, |
- minSteps: minSteps |
- }; |
- }; |
- }; |
- var HorizontalBar = function(data, config, ctx) { |
- var maxSize, scaleHop, calculatedScale, labelHeight, scaleHeight, valueBounds, labelTemplateString, valueHop, widestXLabel, xAxisLength, yAxisPosX, xAxisPosY, barWidth, rotateLabels = 0, |
- msr; |
- ctx.tpchart="HorizontalBar"; |
- setting_new_chart_vars(ctx); |
- |
- if (!dynamicFunction(data, config, ctx)) { |
- if(config.responsive && typeof ctx.firstPass == "undefined") { if(!config.multiGraph) { addResponsiveChart(ctx.ChartNewId,ctx,data,config); } } |
- return; |
- } |
- if(config.responsive && typeof ctx.firstPass == "undefined") { |
- if(!config.multiGraph) { |
- addResponsiveChart(ctx.ChartNewId,ctx,data,config); |
- subUpdateChart(ctx,data,config); |
- return; |
- } else { ctx.firstPass=1; } |
- } |
- |
- if (config.reverseOrder && typeof ctx.reversed == "undefined") { |
- ctx.reversed=true; |
- data = reverseData(data); |
- } |
- |
- if (typeof jsGraphAnnotate[ctx.ChartNewId] == "undefined") jsGraphAnnotate[ctx.ChartNewId] = new Array(); |
- else if (!config.multiGraph) clearAnnotate(ctx.ChartNewId); |
- |
- defMouse(ctx, data, config); |
- setRect(ctx, config); |
- |
- msr = setMeasures(data, config, ctx, height, width, "nihil", [""], true, true, true, true, true, "StackedBar"); |
- valueBounds = getValueBounds(); |
- |
- if(valueBounds.maxSteps>0 && valueBounds.minSteps>0) { |
- //Check and set the scale |
- labelTemplateString = (config.scaleShowLabels) ? config.scaleLabel : ""; |
- if (!config.scaleOverride) { |
- calculatedScale = calculateScale(1, config, valueBounds.maxSteps, valueBounds.minSteps, valueBounds.maxValue, valueBounds.minValue, labelTemplateString); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalBar"); |
- } else { |
- calculatedScale = { |
- steps: config.scaleSteps, |
- stepValue: config.scaleStepWidth, |
- graphMin: config.scaleStartValue, |
- graphMax: config.scaleStartValue + config.scaleSteps * config.scaleStepWidth, |
- labels: [] |
- } |
- populateLabels(1, config, labelTemplateString, calculatedScale.labels, calculatedScale.steps, config.scaleStartValue, calculatedScale.graphMax, config.scaleStepWidth); |
- msr = setMeasures(data, config, ctx, height, width, calculatedScale.labels, null, true, true, true, true, true, "HorizontalBar"); |
- } |
- msr.availableHeight = msr.availableHeight - config.scaleTickSizeBottom - config.scaleTickSizeTop; |
- msr.availableWidth = msr.availableWidth - config.scaleTickSizeLeft - config.scaleTickSizeRight; |
- scaleHop = Math.floor(msr.availableHeight / data.labels.length); |
- valueHop = Math.floor(msr.availableWidth / (calculatedScale.steps)); |
- if (valueHop == 0 || config.fullWidthGraph) valueHop = (msr.availableWidth / calculatedScale.steps); |
- msr.clrwidth = msr.clrwidth - (msr.availableWidth - (calculatedScale.steps * valueHop)); |
- msr.availableWidth = (calculatedScale.steps) * valueHop; |
- msr.availableHeight = (data.labels.length) * scaleHop; |
- yAxisPosX = msr.leftNotUsableSize + config.scaleTickSizeLeft; |
- xAxisPosY = msr.topNotUsableSize + msr.availableHeight + config.scaleTickSizeTop; |
- barWidth = (scaleHop - config.scaleGridLineWidth * 2 - (config.barValueSpacing * 2) - (config.barDatasetSpacing * data.datasets.length - 1) - ((config.barStrokeWidth / 2) * data.datasets.length - 1)) / data.datasets.length; |
- if(barWidth>=0 && barWidth<=1)barWidth=1; |
- if(barWidth<0 && barWidth>=-1)barWidth=-1; |
- var zeroY = 0; |
- if (valueBounds.minValue < 0) { |
- var zeroY = calculateOffset(config.logarithmic, 0, calculatedScale, valueHop); |
- } |
- drawLabels(); |
- animationLoop(config, drawScale, drawBars, ctx, msr.clrx, msr.clry, msr.clrwidth, msr.clrheight, yAxisPosX + msr.availableWidth / 2, xAxisPosY - msr.availableHeight / 2, yAxisPosX, xAxisPosY, data); |
- } else { |
- testRedraw(ctx,data,config); |
- } |
- |
- function drawBars(animPc) { |
- var cumvalue = new Array(); |
- var totvalue = new Array(); |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- cumvalue[j] = 0; |
- totvalue[j] = 0; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) totvalue[j] += 1 * data.datasets[i].data[j]; |
- } |
- ctx.lineWidth = config.barStrokeWidth; |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (animPc >= 1) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- } |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- var currentAnimPc = animationCorrection(animPc, data, config, i, j, 1).animVal; |
- if (currentAnimPc > 1) currentAnimPc = currentAnimPc - 1; |
- var barOffset = xAxisPosY + config.barValueSpacing - scaleHop * (j + 1) + barWidth * i + config.barDatasetSpacing * i + config.barStrokeWidth * i; |
- var barHeight = currentAnimPc * (calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) - zeroY) + (config.barStrokeWidth / 2); |
- ctx.fillStyle = config.defaultFillColor; |
- if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "HorizontalBar", ctx, yAxisPosX+zeroY, barOffset, yAxisPosX + zeroY + barHeight, barOffset + barWidth); |
- else if (typeof(data.datasets[i].fillColor) == "string") { |
- ctx.fillStyle = data.datasets[i].fillColor; |
- } else if (typeof(data.datasets[i].fillColor) == "object") { |
- if (typeof(data.datasets[i].fillColor[0]) == "string") { |
- ctx.fillStyle = data.datasets[i].fillColor[Min([data.datasets[i].fillColor.length - 1, j])]; |
- } |
- } |
- ctx.strokeStyle = config.defaultStrokeColor; |
- if (typeof data.datasets[i].strokeColor == "function") ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, j, currentAnimPc, 1 * data.datasets[i].data[j], "HorizontalBar", ctx, yAxisPosX, barOffset, yAxisPosX + barHeight, barOffset + barWidth); |
- else if (typeof(data.datasets[i].strokeColor) == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor; |
- } else if (typeof(data.datasets[i].strokeColor) == "object") { |
- if (typeof(data.datasets[i].strokeColor[0]) == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor[Min([data.datasets[i].strokeColor.length - 1, j])]; |
- } |
- } |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- roundRect(ctx, barOffset, yAxisPosX+zeroY, barWidth, barHeight, config.barShowStroke, config.barBorderRadius, 0); |
- cumvalue[j] += 1 * data.datasets[i].data[j]; |
- if (animPc >= 1) { |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- else lgtxt2 = ""; |
- t1 = yAxisPosX + zeroY; |
- t2 = yAxisPosX + calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2) |
- if (t1 > t2) { |
- t3 = t1; |
- t1 = t2; |
- t2 = t3 |
- } |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["RECT", t1, barOffset + barWidth, t2, barOffset, lgtxt, lgtxt2, 1 * data.datasets[i].data[j], cumvalue[j], totvalue[j], i, j]; |
- } |
- } |
- } |
- } |
- if (animPc >= 1 && config.inGraphDataShow) { |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- cumvalue[j] = 0; |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- if (typeof(data.labels[j]) == "string") lgtxt2 = data.labels[j].trim(); |
- ctx.save(); |
- ctx.textAlign = config.inGraphDataAlign; |
- ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- var barOffset = xAxisPosY + config.barValueSpacing - scaleHop * (j + 1) + barWidth * i + config.barDatasetSpacing * i + config.barStrokeWidth * i; |
- t1 = yAxisPosX + zeroY; |
- t2 = yAxisPosX + calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2) |
- if (t1 > t2) { |
- t3 = t1; |
- t1 = t2; |
- t2 = t3 |
- } |
- ctx.beginPath(); |
- var yPos = 0, |
- xPos = 0; |
- if (config.inGraphDataYPosition == 1) { |
- yPos = barOffset - config.inGraphDataPaddingY + barWidth; |
- } else if (config.inGraphDataYPosition == 2) { |
- yPos = barOffset + barWidth / 2 - config.inGraphDataPaddingY; |
- } else if (config.inGraphDataYPosition == 3) { |
- yPos = barOffset - config.inGraphDataPaddingY; |
- } |
- if (config.inGraphDataXPosition == 1) { |
- xPos = yAxisPosX + zeroY + config.inGraphDataPaddingX; |
- } else if (config.inGraphDataXPosition == 2) { |
- xPos = yAxisPosX + (calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2)) / 2 + config.inGraphDataPaddingX; |
- } else if (config.inGraphDataXPosition == 3) { |
- xPos = yAxisPosX + calculateOffset(config.logarithmic, 1 * data.datasets[i].data[j], calculatedScale, valueHop) + (config.barStrokeWidth / 2) + config.inGraphDataPaddingX; |
- } |
- ctx.translate(xPos, yPos); |
- cumvalue[j] += 1 * data.datasets[i].data[j]; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, lgtxt2, config.fmtV2), |
- v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3), |
- v4: fmtChartJS(config, cumvalue[j], config.fmtV4), |
- v5: fmtChartJS(config, totvalue[j], config.fmtV5), |
- v6: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV6), config.roundPct), |
- v7: fmtChartJS(config, t1, config.fmtV7), |
- v8: fmtChartJS(config, barOffset + barWidth, config.fmtV8), |
- v9: fmtChartJS(config, t2, config.fmtV9), |
- v10: fmtChartJS(config, barOffset, config.fmtV10), |
- v11: fmtChartJS(config, i, config.fmtV11), |
- v12: fmtChartJS(config, j, config.fmtV12), |
- data: data |
- }); |
- ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- ctx.restore(); |
- } |
- } |
- } |
- } |
- if(msr.legendMsr.dispLegend)drawLegend(msr.legendMsr,data,config,ctx,"HorizontalBar"); |
- }; |
- |
- function roundRect(ctx, x, y, w, h, stroke, radius, zeroY) { |
- ctx.beginPath(); |
- ctx.moveTo(y + zeroY, x + radius); |
- ctx.lineTo(y + zeroY, x + w - radius); |
- ctx.quadraticCurveTo(y + zeroY, x + w, y + zeroY, x + w); |
- ctx.lineTo(y + h - radius, x + w); |
- ctx.quadraticCurveTo(y + h, x + w, y + h, x + w - radius); |
- ctx.lineTo(y + h, x + radius); |
- ctx.quadraticCurveTo(y + h, x, y + h - radius, x); |
- ctx.lineTo(y + zeroY, x); |
- ctx.quadraticCurveTo(y + zeroY, x, y + zeroY, x + radius); |
- if (stroke) ctx.stroke(); |
- ctx.closePath(); |
- ctx.fill(); |
- }; |
- |
- function drawScale() { |
- //X axis line |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY); |
- ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY); |
- ctx.stroke(); |
- for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) { |
- if (i >= 0) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX + i * valueHop, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- //Check i isnt 0, so we dont go over the Y axis twice. |
- if (config.scaleShowGridLines && i > 0 && i % config.scaleXGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- } else { |
- ctx.lineTo(yAxisPosX + i * valueHop, xAxisPosY); |
- } |
- ctx.stroke(); |
- } |
- } |
- //Y axis |
- ctx.lineWidth = config.scaleLineWidth; |
- ctx.strokeStyle = config.scaleLineColor; |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX, xAxisPosY + config.scaleTickSizeBottom); |
- ctx.lineTo(yAxisPosX, xAxisPosY - msr.availableHeight - config.scaleTickSizeTop); |
- ctx.stroke(); |
- for (var j = 0; j < data.labels.length; j++) { |
- ctx.beginPath(); |
- ctx.moveTo(yAxisPosX - config.scaleTickSizeLeft, xAxisPosY - ((j + 1) * scaleHop)); |
- ctx.lineWidth = config.scaleGridLineWidth; |
- ctx.strokeStyle = config.scaleGridLineColor; |
- if (config.scaleShowGridLines && j % config.scaleYGridLinesStep == 0) { |
- ctx.lineTo(yAxisPosX + msr.availableWidth + config.scaleTickSizeRight, xAxisPosY - ((j + 1) * scaleHop)); |
- } else { |
- ctx.lineTo(yAxisPosX, xAxisPosY - ((j + 1) * scaleHop)); |
- } |
- ctx.stroke(); |
- } |
- }; |
- |
- function drawLabels() { |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- //X axis line |
- if (config.scaleShowLabels && (config.xAxisTop || config.xAxisBottom)) { |
- ctx.textBaseline = "top"; |
- if (msr.rotateLabels > 90) { |
- ctx.save(); |
- ctx.textAlign = "left"; |
- } else if (msr.rotateLabels > 0) { |
- ctx.save(); |
- ctx.textAlign = "right"; |
- } else { |
- ctx.textAlign = "center"; |
- } |
- ctx.fillStyle = config.scaleFontColor; |
- if (config.xAxisBottom) { |
- for (var i = ((config.showYAxisMin) ? -1 : 0); i < calculatedScale.steps; i++) { |
- ctx.save(); |
- if (msr.rotateLabels > 0) { |
- ctx.translate(yAxisPosX + (i + 1) * valueHop - msr.highestXLabel / 2, msr.xLabelPos); |
- ctx.rotate(-(msr.rotateLabels * (Math.PI / 180))); |
- ctx.fillTextMultiLine(calculatedScale.labels[i + 1], 0, 0, ctx.textBaseline, config.scaleFontSize); |
- } else { |
- ctx.fillTextMultiLine(calculatedScale.labels[i + 1], yAxisPosX + (i + 1) * valueHop, msr.xLabelPos, ctx.textBaseline, config.scaleFontSize); |
- } |
- ctx.restore(); |
- } |
- } |
- } |
- //Y axis |
- ctx.textAlign = "right"; |
- ctx.textBaseline = "middle"; |
- for (var j = 0; j < data.labels.length; j++) { |
- if (config.yAxisLeft) { |
- ctx.textAlign = "right"; |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX - (config.scaleTickSizeLeft + config.yAxisSpaceRight), xAxisPosY - (j * scaleHop) - scaleHop / 2, ctx.textBaseline, config.scaleFontSize); |
- } |
- if (config.yAxisRight) { |
- ctx.textAlign = "left"; |
- ctx.fillTextMultiLine(fmtChartJS(config, data.labels[j], config.fmtXLabel), yAxisPosX + msr.availableWidth + (config.scaleTickSizeRight + config.yAxisSpaceRight), xAxisPosY - (j * scaleHop) - scaleHop / 2, ctx.textBaseline, config.scaleFontSize); |
- } |
- } |
- }; |
- |
- function getValueBounds() { |
- var upperValue = Number.MIN_VALUE; |
- var lowerValue = Number.MAX_VALUE; |
- for (var i = 0; i < data.datasets.length; i++) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- if (1 * data.datasets[i].data[j] > upperValue) { |
- upperValue = 1 * data.datasets[i].data[j] |
- }; |
- if (1 * data.datasets[i].data[j] < lowerValue) { |
- lowerValue = 1 * data.datasets[i].data[j] |
- }; |
- } |
- }; |
- if (Math.abs(upperValue - lowerValue) < 0.00000001) { |
- upperValue = Max([upperValue * 2, 1]); |
- lowerValue = 0; |
- } |
- // AJOUT CHANGEMENT |
- if (!isNaN(config.graphMin)) lowerValue = config.graphMin; |
- if (!isNaN(config.graphMax)) upperValue = config.graphMax; |
- |
- labelHeight = config.scaleFontSize; |
- scaleHeight = msr.availableHeight; |
- |
- var maxSteps = Math.floor((scaleHeight / (labelHeight * 0.66))); |
- var minSteps = Math.floor((scaleHeight / labelHeight * 0.5)); |
- return { |
- maxValue: upperValue, |
- minValue: lowerValue, |
- maxSteps: maxSteps, |
- minSteps: minSteps |
- }; |
- }; |
- }; |
- |
- function calculateOffset(logarithmic, val, calculatedScale, scaleHop) { |
- if (!logarithmic) { // no logarithmic scale |
- var outerValue = calculatedScale.steps * calculatedScale.stepValue; |
- var adjustedValue = val - calculatedScale.graphMin; |
- var scalingFactor = CapValue(adjustedValue / outerValue, 1, 0); |
- return (scaleHop * calculatedScale.steps) * scalingFactor; |
- } else { // logarithmic scale |
- return CapValue(log10(val) * scaleHop - calculateOrderOfMagnitude(calculatedScale.graphMin) * scaleHop, undefined, 0); |
- } |
- }; |
- |
- function animationLoop(config, drawScale, drawData, ctx, clrx, clry, clrwidth, clrheight, midPosX, midPosY, borderX, borderY, data) { |
- var cntiter = 0; |
- var animationCount = 1; |
- var multAnim = 1; |
- if (config.animationStartValue < 0 || config.animationStartValue > 1) config.animation.StartValue = 0; |
- if (config.animationStopValue < 0 || config.animationStopValue > 1) config.animation.StopValue = 1; |
- if (config.animationStopValue < config.animationStartValue) config.animationStopValue = config.animationStartValue; |
- if (isIE() < 9 && isIE() != false) config.animation = false; |
- var animFrameAmount = (config.animation) ? 1 / CapValue(config.animationSteps, Number.MAX_VALUE, 1) : 1, |
- easingFunction = animationOptions[config.animationEasing], |
- percentAnimComplete = (config.animation) ? 0 : 1; |
- if (config.animation && config.animationStartValue > 0 && config.animationStartValue <= 1) { |
- while (percentAnimComplete < config.animationStartValue) { |
- cntiter++; |
- percentAnimComplete += animFrameAmount; |
- } |
- } |
- var beginAnim = cntiter; |
- var beginAnimPct = percentAnimComplete; |
- if (typeof drawScale !== "function") drawScale = function() {}; |
- if (config.clearRect) requestAnimFrame(animLoop); |
- else animLoop(); |
- |
- function animateFrame() { |
- var easeAdjustedAnimationPercent = (config.animation) ? CapValue(easingFunction(percentAnimComplete), null, 0) : 1; |
- if (1 * cntiter >= 1 * CapValue(config.animationSteps, Number.MAX_VALUE, 1) || config.animation == false || ctx.firstPass==3 || ctx.firstPass==4 || ctx.firstPass==8 || ctx.firstPass==9) easeAdjustedAnimationPercent = 1; |
- else if (easeAdjustedAnimationPercent >= 1) easeAdjustedAnimationPercent = 0.9999; |
- if (config.animation && !(isIE() < 9 && isIE() != false) && config.clearRect) ctx.clearRect(clrx, clry, clrwidth, clrheight); |
- dispCrossImage(ctx, config, midPosX, midPosY, borderX, borderY, false, data, easeAdjustedAnimationPercent, cntiter); |
- dispCrossText(ctx, config, midPosX, midPosY, borderX, borderY, false, data, easeAdjustedAnimationPercent, cntiter); |
- if (config.scaleOverlay) { |
- drawData(easeAdjustedAnimationPercent); |
- drawScale(); |
- } else { |
- drawScale(); |
- drawData(easeAdjustedAnimationPercent); |
- } |
- dispCrossImage(ctx, config, midPosX, midPosY, borderX, borderY, true, data, easeAdjustedAnimationPercent, cntiter); |
- dispCrossText(ctx, config, midPosX, midPosY, borderX, borderY, true, data, easeAdjustedAnimationPercent, cntiter); |
- }; |
- |
- function animLoop() { |
- //We need to check if the animation is incomplete (less than 1), or complete (1). |
- cntiter += multAnim; |
- percentAnimComplete += multAnim * animFrameAmount; |
- if (cntiter == config.animationSteps || config.animation == false || ctx.firstPass==3 || ctx.firstPass==4 || ctx.firstPass==8 || ctx.firstPass==9) percentAnimComplete = 1; |
- else if (percentAnimComplete >= 1) percentAnimComplete = 0.999; |
- animateFrame(); |
- //Stop the loop continuing forever |
- if (multAnim == -1 && cntiter <= beginAnim) { |
- if (typeof config.onAnimationComplete == "function" && ctx.runanimationcompletefunction==true) config.onAnimationComplete(ctx, config, data, 0, animationCount + 1); |
- multAnim = 1; |
- requestAnimFrame(animLoop); |
- } else if (percentAnimComplete < config.animationStopValue) { |
- requestAnimFrame(animLoop); |
- } else { |
- if ((animationCount < config.animationCount || config.animationCount == 0) && (ctx.firstPass ==1 || ctx.firstPass!=2)) { |
- animationCount++; |
- if (config.animationBackward && multAnim == 1) { |
- percentAnimComplete -= animFrameAmount; |
- multAnim = -1; |
- } else { |
- multAnim = 1; |
- cntiter = beginAnim - 1; |
- percentAnimComplete = beginAnimPct - animFrameAmount; |
- } |
- window.setTimeout(animLoop, config.animationPauseTime*1000); |
- } else { |
- if(!testRedraw(ctx,data,config) ) { |
- if (typeof config.onAnimationComplete == "function" && ctx.runanimationcompletefunction==true) { |
- config.onAnimationComplete(ctx, config, data, 1, animationCount + 1); |
- ctx.runanimationcompletefunction=false; |
- } |
- } |
- } |
- |
- } |
- }; |
- }; |
- //Declare global functions to be called within this namespace here. |
- // shim layer with setTimeout fallback |
- var requestAnimFrame = (function() { |
- return window.requestAnimationFrame || |
- window.webkitRequestAnimationFrame || |
- window.mozRequestAnimationFrame || |
- window.oRequestAnimationFrame || |
- window.msRequestAnimationFrame || |
- function(callback) { |
- window.setTimeout(callback, 1000 / 60); |
- }; |
- })(); |
- |
- function calculateScale(axis, config, maxSteps, minSteps, maxValue, minValue, labelTemplateString) { |
- var graphMin, graphMax, graphRange, stepValue, numberOfSteps, valueRange, rangeOrderOfMagnitude, decimalNum; |
- var logarithmic, yAxisMinimumInterval; |
- if (axis == 2) { |
- logarithmic = config.logarithmic2; |
- yAxisMinimumInterval = config.yAxisMinimumInterval2; |
- } else { |
- logarithmic = config.logarithmic; |
- yAxisMinimumInterval = config.yAxisMinimumInterval; |
- } |
- if (!logarithmic) { // no logarithmic scale |
- valueRange = maxValue - minValue; |
- rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange); |
- graphMin = Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude); |
- graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude); |
- if (typeof yAxisMinimumInterval == "number") { |
- graphMin = graphMin - (graphMin % yAxisMinimumInterval); |
- while (graphMin > minValue) graphMin = graphMin - yAxisMinimumInterval; |
- if (graphMax % yAxisMinimumInterval > 0.0000001 && graphMax % yAxisMinimumInterval < yAxisMinimumInterval - 0.0000001) { |
- graphMax = roundScale(config, (1 + Math.floor(graphMax / yAxisMinimumInterval)) * yAxisMinimumInterval); |
- } |
- while (graphMax < maxValue) graphMax = graphMax + yAxisMinimumInterval; |
- } |
- } else { // logarithmic scale |
- var minMag = calculateOrderOfMagnitude(minValue); |
- var maxMag = calculateOrderOfMagnitude(maxValue) + 1; |
- graphMin = Math.pow(10, minMag); |
- graphMax = Math.pow(10, maxMag); |
- rangeOrderOfMagnitude = maxMag - minMag; |
- } |
- graphRange = graphMax - graphMin; |
- stepValue = Math.pow(10, rangeOrderOfMagnitude); |
- numberOfSteps = Math.round(graphRange / stepValue); |
- if (!logarithmic) { // no logarithmic scale |
- //Compare number of steps to the max and min for that size graph, and add in half steps if need be. |
- var stopLoop = false; |
- while (!stopLoop && (numberOfSteps < minSteps || numberOfSteps > maxSteps)) { |
- if (numberOfSteps < minSteps) { |
- if (typeof yAxisMinimumInterval == "number") { |
- if (stepValue / 2 < yAxisMinimumInterval) stopLoop = true; |
- } |
- if (!stopLoop) { |
- stepValue /= 2; |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } |
- } else { |
- stepValue *= 2; |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } |
- } |
- |
- if (typeof yAxisMinimumInterval == "number") { |
- if (stepValue < yAxisMinimumInterval) { |
- stepValue = yAxisMinimumInterval; |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } |
- if (stepValue % yAxisMinimumInterval > 0.0000001 && stepValue % yAxisMinimumInterval < yAxisMinimumInterval - 0.0000001) { |
- if ((2 * stepValue) % yAxisMinimumInterval < 0.0000001 || (2 * stepValue) % yAxisMinimumInterval > yAxisMinimumInterval - 0.0000001) { |
- stepValue = 2 * stepValue; |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } else { |
- stepValue = roundScale(config, (1 + Math.floor(stepValue / yAxisMinimumInterval)) * yAxisMinimumInterval); |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } |
- } |
- } |
- } else { // logarithmic scale |
- numberOfSteps = rangeOrderOfMagnitude; // so scale is 10,100,1000,... |
- } |
- var labels = []; |
- populateLabels(1, config, labelTemplateString, labels, numberOfSteps, graphMin, graphMax, stepValue); |
- return { |
- steps: numberOfSteps, |
- stepValue: stepValue, |
- graphMin: graphMin, |
- labels: labels, |
- maxValue: maxValue |
- } |
- }; |
- |
- function calculateScaleOld(config, maxSteps, minSteps, maxValue, minValue, labelTemplateString) { |
- var graphMin, graphMax, graphRange, stepValue, numberOfSteps, valueRange, rangeOrderOfMagnitude, decimalNum; |
- if (!config.logarithmic) { // no logarithmic scale |
- valueRange = maxValue - minValue; |
- rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange); |
- graphMin = Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude); |
- graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude); |
- if (typeof config.yAxisMinimumInterval == "number") { |
- graphMin = graphMin - (graphMin % config.yAxisMinimumInterval); |
- while (graphMin > minValue) graphMin = graphMin - config.yAxisMinimumInterval; |
- if (graphMax % config.yAxisMinimumInterval > 0.0000001 && graphMax % config.yAxisMinimumInterval < config.yAxisMinimumInterval - 0.0000001) { |
- graphMax = roundScale(config, (1 + Math.floor(graphMax / config.yAxisMinimumInterval)) * config.yAxisMinimumInterval); |
- } |
- while (graphMax < maxValue) graphMax = graphMax + config.yAxisMinimumInterval; |
- } |
- } else { // logarithmic scale |
- var minMag = calculateOrderOfMagnitude(minValue); |
- var maxMag = calculateOrderOfMagnitude(maxValue) + 1; |
- graphMin = Math.pow(10, minMag); |
- graphMax = Math.pow(10, maxMag); |
- rangeOrderOfMagnitude = maxMag - minMag; |
- } |
- graphRange = graphMax - graphMin; |
- stepValue = Math.pow(10, rangeOrderOfMagnitude); |
- numberOfSteps = Math.round(graphRange / stepValue); |
- if (!config.logarithmic) { // no logarithmic scale |
- //Compare number of steps to the max and min for that size graph, and add in half steps if need be. |
- var stopLoop = false; |
- while (!stopLoop && (numberOfSteps < minSteps || numberOfSteps > maxSteps)) { |
- if (numberOfSteps < minSteps) { |
- if (typeof config.yAxisMinimumInterval == "number") { |
- if (stepValue / 2 < config.yAxisMinimumInterval) stopLoop = true; |
- } |
- if (!stopLoop) { |
- stepValue /= 2; |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } |
- } else { |
- stepValue *= 2; |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } |
- } |
- if (typeof config.yAxisMinimumInterval == "number") { |
- if (stepValue < config.yAxisMinimumInterval) { |
- stepValue = config.yAxisMinimumInterval; |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } |
- if (stepValue % config.yAxisMinimumInterval > 0.0000001 && stepValue % config.yAxisMinimumInterval < config.yAxisMinimumInterval - 0.0000001) { |
- if ((2 * stepValue) % config.yAxisMinimumInterval < 0.0000001 || (2 * stepValue) % config.yAxisMinimumInterval > config.yAxisMinimumInterval - 0.0000001) { |
- stepValue = 2 * stepValue; |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } else { |
- stepValue = roundScale(config, (1 + Math.floor(stepValue / config.yAxisMinimumInterval)) * config.yAxisMinimumInterval); |
- numberOfSteps = Math.round(graphRange / stepValue); |
- } |
- } |
- } |
- } else { // logarithmic scale |
- numberOfSteps = rangeOrderOfMagnitude; // so scale is 10,100,1000,... |
- } |
- var labels = []; |
- populateLabels(1, config, labelTemplateString, labels, numberOfSteps, graphMin, graphMax, stepValue); |
- return { |
- steps: numberOfSteps, |
- stepValue: stepValue, |
- graphMin: graphMin, |
- labels: labels, |
- maxValue: maxValue |
- } |
- }; |
- |
- function roundScale(config, value) { |
- var scldec = 0; |
- var sscl = "" + config.yAxisMinimumInterval; |
- if (sscl.indexOf(".") > 0) { |
- scldec = sscl.substr(sscl.indexOf(".")).length; |
- } |
- return (Math.round(value * Math.pow(10, scldec)) / Math.pow(10, scldec)); |
- } |
- |
- function calculateOrderOfMagnitude(val) { |
- return Math.floor(Math.log(val) / Math.LN10); |
- }; |
- //Populate an array of all the labels by interpolating the string. |
- function populateLabels(axis, config, labelTemplateString, labels, numberOfSteps, graphMin, graphMax, stepValue) { |
- var logarithmic; |
- if (axis == 2) { |
- logarithmic = config.logarithmic2; |
- fmtYLabel = config.fmtYLabel2; |
- } else { |
- logarithmic = config.logarithmic; |
- fmtYLabel = config.fmtYLabel; |
- } |
- if (labelTemplateString) { |
- //Fix floating point errors by setting to fixed the on the same decimal as the stepValue. |
- if (!logarithmic) { // no logarithmic scale |
- for (var i = 0; i < numberOfSteps + 1; i++) { |
- labels.push(tmpl(labelTemplateString, { |
- value: fmtChartJS(config, 1 * ((graphMin + (stepValue * i)).toFixed(getDecimalPlaces(stepValue))), fmtYLabel) |
- })); |
- } |
- } else { // logarithmic scale 10,100,1000,... |
- var value = graphMin; |
- for (var i = 0; i < numberOfSteps + 1; i++) { |
- labels.push(tmpl(labelTemplateString, { |
- value: fmtChartJS(config, 1 * value.toFixed(getDecimalPlaces(value)), fmtYLabel) |
- })); |
- value *= 10; |
- } |
- } |
- } |
- }; |
- //Max value from array |
- function Max(array) { |
- return Math.max.apply(Math, array); |
- }; |
- //Min value from array |
- function Min(array) { |
- return Math.min.apply(Math, array); |
- }; |
- //Default if undefined |
- function Default(userDeclared, valueIfFalse) { |
- if (!userDeclared) { |
- return valueIfFalse; |
- } else { |
- return userDeclared; |
- } |
- }; |
- //Apply cap a value at a high or low number |
- function CapValue(valueToCap, maxValue, minValue) { |
- if (isNumber(maxValue)) { |
- if (valueToCap > maxValue) { |
- return maxValue; |
- } |
- } |
- if (isNumber(minValue)) { |
- if (valueToCap < minValue) { |
- return minValue; |
- } |
- } |
- return valueToCap; |
- }; |
- |
- function getDecimalPlaces(num) { |
- var numberOfDecimalPlaces; |
- if (num % 1 != 0) { |
- return num.toString().split(".")[1].length |
- } else { |
- return 0; |
- } |
- }; |
- |
- function mergeChartConfig(defaults, userDefined) { |
- var returnObj = {}; |
- for (var attrname in defaults) { |
- returnObj[attrname] = defaults[attrname]; |
- } |
- for (var attrname in userDefined) { |
- returnObj[attrname] = userDefined[attrname]; |
- } |
- return returnObj; |
- }; |
- //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/ |
- var cache = {}; |
- |
- function tmpl(str, data) { |
- // Figure out if we're getting a template, or if we need to |
- // load the template - and be sure to cache the result. |
- var fn = !/\W/.test(str) ? |
- cache[str] = cache[str] || |
- tmpl(document.getElementById(str).innerHTML) : |
- // Generate a reusable function that will serve as a template |
- // generator (and which will be cached). |
- new Function("obj", |
- "var p=[],print=function(){p.push.apply(p,arguments);};" + |
- // Introduce the data as local variables using with(){} |
- "with(obj){p.push('" + |
- // Convert the template into pure JavaScript |
- str |
- .replace(/[\r\t\n]/g, " ") |
- .split("<%").join("\t") |
- .replace(/((^|%>)[^\t]*)'/g, "$1\r") |
- .replace(/\t=(.*?)%>/g, "',$1,'") |
- .split("\t").join("');") |
- .split("%>").join("p.push('") |
- .split("\r").join("\\'") + "');}return p.join('');"); |
- // Provide some basic currying to the user |
- return data ? fn(data) : fn; |
- }; |
- |
- function dispCrossText(ctx, config, posX, posY, borderX, borderY, overlay, data, animPC, cntiter) { |
- var i, disptxt, txtposx, txtposy, textAlign, textBaseline; |
- for (i = 0; i < config.crossText.length; i++) { |
- if (config.crossText[i] != "" && config.crossTextOverlay[Min([i, config.crossTextOverlay.length - 1])] == overlay && ((cntiter == 1 && config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "first") || config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == cntiter || config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "all" || (animPC == 1 && config.crossTextIter[Min([i, config.crossTextIter.length - 1])] == "last"))) { |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.crossTextFontStyle[Min([i, config.crossTextFontStyle.length - 1])] + " " + config.crossTextFontSize[Min([i, config.crossTextFontSize.length - 1])] + "px " + config.crossTextFontFamily[Min([i, config.crossTextFontFamily.length - 1])]; |
- ctx.fillStyle = config.crossTextFontColor[Min([i, config.crossTextFontColor.length - 1])]; |
- textAlign = config.crossTextAlign[Min([i, config.crossTextAlign.length - 1])]; |
- textBaseline = config.crossTextBaseline[Min([i, config.crossTextBaseline.length - 1])]; |
- txtposx = 1 * config.crossTextPosX[Min([i, config.crossTextPosX.length - 1])]; |
- txtposy = 1 * config.crossTextPosY[Min([i, config.crossTextPosY.length - 1])]; |
- switch (1 * config.crossTextRelativePosX[Min([i, config.crossTextRelativePosX.length - 1])]) { |
- case 0: |
- if (textAlign == "default") textAlign = "left"; |
- break; |
- case 1: |
- txtposx += borderX; |
- if (textAlign == "default") textAlign = "right"; |
- break; |
- case 2: |
- txtposx += posX; |
- if (textAlign == "default") textAlign = "center"; |
- break; |
- case -2: |
- txtposx += context.canvas.width / 2; |
- if (textAlign == "default") textAlign = "center"; |
- break; |
- case 3: |
- txtposx += txtposx + 2 * posX - borderX; |
- if (textAlign == "default") textAlign = "left"; |
- break; |
- case 4: |
- // posX=width; |
- txtposx += context.canvas.width; |
- if (textAlign == "default") textAlign = "right"; |
- break; |
- default: |
- txtposx += posX; |
- if (textAlign == "default") textAlign = "center"; |
- break; |
- } |
- switch (1 * config.crossTextRelativePosY[Min([i, config.crossTextRelativePosY.length - 1])]) { |
- case 0: |
- if (textBaseline == "default") textBaseline = "top"; |
- break; |
- case 3: |
- txtposy += borderY; |
- if (textBaseline == "default") textBaseline = "top"; |
- break; |
- case 2: |
- txtposy += posY; |
- if (textBaseline == "default") textBaseline = "middle"; |
- break; |
- case -2: |
- txtposy += context.canvas.height / 2; |
- if (textBaseline == "default") textBaseline = "middle"; |
- break; |
- case 1: |
- txtposy += txtposy + 2 * posY - borderY; |
- if (textBaseline == "default") textBaseline = "bottom"; |
- break; |
- case 4: |
- txtposy += context.canvas.height; |
- if (textBaseline == "default") textBaseline = "bottom"; |
- break; |
- default: |
- txtposy += posY; |
- if (textBaseline == "default") textBaseline = "middle"; |
- break; |
- } |
- ctx.textAlign = textAlign; |
- ctx.textBaseline = textBaseline; |
- ctx.translate(1 * txtposx, 1 * txtposy); |
- ctx.rotate(Math.PI * config.crossTextAngle[Min([i, config.crossTextAngle.length - 1])] / 180); |
- if (config.crossText[i].substring(0, 1) == "%") { |
- if (typeof config.crossTextFunction == "function") disptxt = config.crossTextFunction(i, config.crossText[i], ctx, config, posX, posY, borderX, borderY, overlay, data, animPC); |
- } else disptxt = config.crossText[i]; |
- ctx.fillTextMultiLine(disptxt, 0, 0, ctx.textBaseline, config.crossTextFontSize[Min([i, config.crossTextFontSize.length - 1])]); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- } |
- }; |
- |
- function dispCrossImage(ctx, config, posX, posY, borderX, borderY, overlay, data, animPC, cntiter) { |
- var i, disptxt, imageposx, imageposy, imageAlign, imageBaseline; |
- for (i = 0; i < config.crossImage.length; i++) { |
- if (typeof config.crossImage[i] != "undefined" && config.crossImageOverlay[Min([i, config.crossImageOverlay.length - 1])] == overlay && ((cntiter == -1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "background") || (cntiter == 1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "first") || config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == cntiter || (cntiter != -1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "all") || (animPC == 1 && config.crossImageIter[Min([i, config.crossImageIter.length - 1])] == "last"))) { |
- ctx.save(); |
- ctx.beginPath(); |
- imageAlign = config.crossImageAlign[Min([i, config.crossImageAlign.length - 1])]; |
- imageBaseline = config.crossImageBaseline[Min([i, config.crossImageBaseline.length - 1])]; |
- imageposx = 1 * config.crossImagePosX[Min([i, config.crossImagePosX.length - 1])]; |
- imageposy = 1 * config.crossImagePosY[Min([i, config.crossImagePosY.length - 1])]; |
- switch (1 * config.crossImageRelativePosX[Min([i, config.crossImageRelativePosX.length - 1])]) { |
- case 0: |
- if (imageAlign == "default") imageAlign = "left"; |
- break; |
- case 1: |
- imageposx += borderX; |
- if (imageAlign == "default") imageAlign = "right"; |
- break; |
- case 2: |
- imageposx += posX; |
- if (imageAlign == "default") imageAlign = "center"; |
- break; |
- case -2: |
- imageposx += context.canvas.width / 2; |
- if (imageAlign == "default") imageAlign = "center"; |
- break; |
- case 3: |
- imageposx += imageposx + 2 * posX - borderX; |
- if (imageAlign == "default") imageAlign = "left"; |
- break; |
- case 4: |
- // posX=width; |
- imageposx += context.canvas.width; |
- if (imageAlign == "default") imageAlign = "right"; |
- break; |
- default: |
- imageposx += posX; |
- if (imageAlign == "default") imageAlign = "center"; |
- break; |
- } |
- switch (1 * config.crossImageRelativePosY[Min([i, config.crossImageRelativePosY.length - 1])]) { |
- case 0: |
- if (imageBaseline == "default") imageBaseline = "top"; |
- break; |
- case 3: |
- imageposy += borderY; |
- if (imageBaseline == "default") imageBaseline = "top"; |
- break; |
- case 2: |
- imageposy += posY; |
- if (imageBaseline == "default") imageBaseline = "middle"; |
- break; |
- case -2: |
- imageposy += context.canvas.height / 2; |
- if (imageBaseline == "default") imageBaseline = "middle"; |
- break; |
- case 1: |
- imageposy += imageposy + 2 * posY - borderY; |
- if (imageBaseline == "default") imageBaseline = "bottom"; |
- break; |
- case 4: |
- imageposy += context.canvas.height; |
- if (imageBaseline == "default") imageBaseline = "bottom"; |
- break; |
- default: |
- imageposy += posY; |
- if (imageBaseline == "default") imageBaseline = "middle"; |
- break; |
- } |
- var imageWidth = config.crossImage[i].width; |
- switch (imageAlign) { |
- case "left": |
- break; |
- case "right": |
- imageposx -= imageWidth; |
- break; |
- case "center": |
- imageposx -= (imageWidth / 2); |
- break; |
- default: |
- break; |
- } |
- var imageHeight = config.crossImage[i].height; |
- switch (imageBaseline) { |
- case "top": |
- break; |
- case "bottom": |
- imageposy -= imageHeight; |
- break; |
- case "middle": |
- imageposy -= (imageHeight / 2); |
- break; |
- default: |
- break; |
- } |
- ctx.translate(1 * imageposx, 1 * imageposy); |
- ctx.rotate(Math.PI * config.crossImageAngle[Min([i, config.crossImageAngle.length - 1])] / 180); |
- ctx.drawImage(config.crossImage[i], 0, 0); |
- // ctx.stroke(); |
- ctx.restore(); |
- } |
- } |
- }; |
- //**************************************************************************************** |
- function setMeasures(data, config, ctx, height, width, ylabels, ylabels2, reverseLegend, reverseAxis, drawAxis, drawLegendOnData, legendBox, typegraph) { |
- if (config.canvasBackgroundColor != "none") ctx.canvas.style.background = config.canvasBackgroundColor; |
- var borderWidth = 0; |
- var xAxisLabelPos = 0; |
- var graphTitleHeight = 0; |
- var graphTitlePosY = 0; |
- var graphSubTitleHeight = 0; |
- var graphSubTitlePosY = 0; |
- var footNoteHeight = 0; |
- var footNotePosY = 0; |
- var yAxisUnitHeight = 0; |
- var yAxisUnitPosY = 0; |
- var widestLegend = 0; |
- var nbeltLegend = 0; |
- var nbLegendLines = 0; |
- var nbLegendCols = 0; |
- var spaceLegendHeight = 0; |
- var xFirstLegendTextPos = 0; |
- var yFirstLegendTextPos = 0; |
- var xLegendBorderPos = 0; |
- var yLegendBorderPos = 0; |
- var yAxisLabelWidth = 0; |
- var yAxisLabelPosLeft = 0; |
- var yAxisLabelPosRight = 0; |
- var xAxisLabelHeight = 0; |
- var xLabelHeight = 0; |
- var widestXLabel = 1; |
- var highestXLabel = 1; |
- var widestYLabel = 0; |
- var highestYLabel = 1; |
- var widestYLabel2 = 0; |
- var highestYLabel2 = 1; |
- var leftNotUsableSize = 0; |
- var rightNotUsableSize = 0; |
- var rotateLabels = 0; |
- var xLabelPos = 0; |
- var legendBorderWidth = 0; |
- var legendBorderHeight = 0; |
- |
- ctx.widthAtSetMeasures=width; |
- ctx.heightAtSetMeasures=height; |
- |
- // Borders |
- if (config.canvasBorders) borderWidth = config.canvasBordersWidth; |
- // compute widest X label |
- if (drawAxis) { |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- for (var i = 0; i < data.labels.length; i++) { |
- var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, data.labels[i], config.fmtXLabel), config.scaleFontSize); |
- //If the text length is longer - make that equal to longest text! |
- widestXLabel = (textMsr.textWidth > widestXLabel) ? textMsr.textWidth : widestXLabel; |
- highestXLabel = (textMsr.textHeight > highestXLabel) ? textMsr.textHeight : highestXLabel; |
- } |
- if (widestXLabel < config.xScaleLabelsMinimumWidth) { |
- widestXLabel = config.xScaleLabelsMinimumWidth; |
- } |
- } |
- // compute Y Label Width |
- if (drawAxis) { |
- widestYLabel = 1; |
- if (ylabels != null && ylabels != "nihil") { |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- for (var i = ylabels.length - 1; i >= 0; i--) { |
- if (typeof(ylabels[i]) == "string") { |
- if (ylabels[i].trim() != "") { |
- var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, ylabels[i], config.fmtYLabel), config.scaleFontSize); |
- //If the text length is longer - make that equal to longest text! |
- widestYLabel = (textMsr.textWidth > widestYLabel) ? textMsr.textWidth : widestYLabel; |
- highestYLabel = (textMsr.textHeight > highestYLabel) ? textMsr.textHeight : highestYLabel; |
- } |
- } |
- } |
- } |
- if (widestYLabel < config.yScaleLabelsMinimumWidth) { |
- widestYLabel = config.yScaleLabelsMinimumWidth; |
- } |
- widestYLabel2 = 1; |
- if (ylabels2 != null && config.yAxisRight) { |
- ctx.font = config.scaleFontStyle + " " + config.scaleFontSize + "px " + config.scaleFontFamily; |
- for (var i = ylabels2.length - 1; i >= 0; i--) { |
- if (typeof(ylabels2[i]) == "string") { |
- if (ylabels2[i].trim() != "") { |
- var textMsr = ctx.measureTextMultiLine(fmtChartJS(config, ylabels2[i], config.fmtYLabel2), config.scaleFontSize); |
- //If the text length is longer - make that equal to longest text! |
- widestYLabel2 = (textMsr.textWidth > widestYLabel2) ? textMsr.textWidth : widestYLabel2; |
- highestYLabel2 = (textMsr.textHeight > highestYLabel2) ? textMsr.textHeight : highestYLabel2; |
- } |
- } |
- } |
- } else { |
- widestYLabel2 = widestYLabel; |
- } |
- if (widestYLabel2 < config.yScaleLabelsMinimumWidth) { |
- widestYLabel2 = config.yScaleLabelsMinimumWidth; |
- } |
- } |
- // yAxisLabel |
- leftNotUsableSize = borderWidth + config.spaceLeft |
- rightNotUsableSize = borderWidth + config.spaceRight; |
- if (drawAxis) { |
- if (typeof(config.yAxisLabel) != "undefined") { |
- if (config.yAxisLabel.trim() != "") { |
- yAxisLabelWidth = (config.yAxisFontSize + config.yAxisLabelSpaceLeft + config.yAxisLabelSpaceRight); |
- yAxisLabelPosLeft = borderWidth + config.spaceLeft + config.yAxisLabelSpaceLeft + config.yAxisFontSize; |
- yAxisLabelPosRight = width - borderWidth - config.spaceRight - config.yAxisLabelSpaceLeft - config.yAxisFontSize; |
- } |
- } |
- if (config.yAxisLeft) { |
- if (reverseAxis == false) leftNotUsableSize = borderWidth + config.spaceLeft + yAxisLabelWidth + widestYLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight; |
- else leftNotUsableSize = borderWidth + config.spaceLeft + yAxisLabelWidth + widestXLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight; |
- } |
- if (config.yAxisRight) { |
- if (reverseAxis == false) rightNotUsableSize = borderWidth + config.spaceRight + yAxisLabelWidth + widestYLabel2 + config.yAxisSpaceLeft + config.yAxisSpaceRight; |
- else rightNotUsableSize = borderWidth + config.spaceRight + yAxisLabelWidth + widestXLabel + config.yAxisSpaceLeft + config.yAxisSpaceRight; |
- } |
- } |
- availableWidth = width - leftNotUsableSize - rightNotUsableSize; |
- // Title |
- if (config.graphTitle.trim() != "") { |
- graphTitleHeight = (config.graphTitleFontSize + config.graphTitleSpaceBefore + config.graphTitleSpaceAfter); |
- graphTitlePosY = borderWidth + config.spaceTop + graphTitleHeight - config.graphTitleSpaceAfter; |
- } |
- // subTitle |
- if (config.graphSubTitle.trim() != "") { |
- graphSubTitleHeight = (config.graphSubTitleFontSize + config.graphSubTitleSpaceBefore + config.graphSubTitleSpaceAfter); |
- graphSubTitlePosY = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight - config.graphSubTitleSpaceAfter; |
- } |
- // yAxisUnit |
- if (drawAxis) { |
- if (config.yAxisUnit.trim() != "") { |
- yAxisUnitHeight = (config.yAxisUnitFontSize + config.yAxisUnitSpaceBefore + config.yAxisUnitSpaceAfter); |
- yAxisUnitPosY = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight + yAxisUnitHeight - config.yAxisUnitSpaceAfter; |
- } |
- } |
- topNotUsableSize = borderWidth + config.spaceTop + graphTitleHeight + graphSubTitleHeight + yAxisUnitHeight + config.graphSpaceBefore; |
- // footNote |
- if (typeof(config.footNote) != "undefined") { |
- if (config.footNote.trim() != "") { |
- footNoteHeight = (config.footNoteFontSize + config.footNoteSpaceBefore + config.footNoteSpaceAfter); |
- footNotePosY = height - config.spaceBottom - borderWidth - config.footNoteSpaceAfter; |
- } |
- } |
- |
- // xAxisLabel |
- if (drawAxis) { |
- if (typeof(config.xAxisLabel) != "undefined") { |
- if (config.xAxisLabel.trim() != "") { |
- xAxisLabelHeight = (config.xAxisFontSize + config.xAxisLabelSpaceBefore + config.xAxisLabelSpaceAfter); |
- xAxisLabelPos = height - borderWidth - config.spaceBottom - footNoteHeight - config.xAxisLabelSpaceAfter; |
- } |
- } |
- } |
- |
- bottomNotUsableHeightWithoutXLabels = borderWidth + config.spaceBottom + footNoteHeight + xAxisLabelHeight + config.graphSpaceAfter; |
- |
- // compute space for Legend |
- if (typeof(config.legend) != "undefined") { |
- if (config.legend == true) { |
- ctx.font = config.legendFontStyle + " " + config.legendFontSize + "px " + config.legendFontFamily; |
- if (drawLegendOnData) { |
- for (var i = data.datasets.length - 1; i >= 0; i--) { |
- if (typeof(data.datasets[i].title) == "string") { |
- if (data.datasets[i].title.trim() != "") { |
- nbeltLegend++; |
- var textLength = ctx.measureText(fmtChartJS(config, data.datasets[i].title, config.fmtLegend)).width; |
- //If the text length is longer - make that equal to longest text! |
- widestLegend = (textLength > widestLegend) ? textLength : widestLegend; |
- } |
- } |
- } |
- } else { |
- for (var i = data.length - 1; i >= 0; i--) { |
- if (typeof(data[i].title) == "string") { |
- if (data[i].title.trim() != "") { |
- nbeltLegend++; |
- var textLength = ctx.measureText(fmtChartJS(config, data[i].title, config.fmtLegend)).width; |
- //If the text length is longer - make that equal to longest text! |
- widestLegend = (textLength > widestLegend) ? textLength : widestLegend; |
- } |
- } |
- } |
- } |
- if (nbeltLegend > 1 || (nbeltLegend == 1 && config.showSingleLegend)) { |
- widestLegend += config.legendBlockSize + config.legendSpaceBetweenBoxAndText; |
- if(config.legendPosY==1 || config.legendPosY==2 || config.legendPosY==3) { |
- availableLegendWidth = availableWidth- config.legendSpaceLeftText - config.legendSpaceRightText; |
- } else { |
- availableLegendWidth = width - config.spaceLeft - config.spaceRight - 2 * (borderWidth) - config.legendSpaceLeftText - config.legendSpaceRightText; |
- } |
- if (config.legendBorders == true) availableLegendWidth -= 2 * (config.legendBordersWidth) - config.legendBordersSpaceLeft - config.legendBordersSpaceRight; |
- maxLegendOnLine = Min([Math.floor((availableLegendWidth + config.legendSpaceBetweenTextHorizontal) / (widestLegend + config.legendSpaceBetweenTextHorizontal)),config.maxLegendCols]); |
- nbLegendLines = Math.ceil(nbeltLegend / maxLegendOnLine); |
- nbLegendCols = Math.ceil(nbeltLegend / nbLegendLines); |
- |
- var legendHeight = nbLegendLines * (config.legendFontSize + config.legendSpaceBetweenTextVertical) - config.legendSpaceBetweenTextVertical + config.legendSpaceBeforeText + config.legendSpaceAfterText; |
- if (config.legendBorders == true) { |
-// legendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter; |
- } |
- |
- switch (config.legendPosY) { |
- case 0: |
- xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2; |
- spaceLegendHeight = legendHeight; |
- if (config.legendBorders == true) { |
- yLegendBorderPos = topNotUsableSize + config.legendBordersSpaceBefore + (config.legendBordersWidth/2); |
- yFirstLegendTextPos = yLegendBorderPos + (config.legendBordersWidth/2) + config.legendSpaceBeforeText+config.legendFontSize; |
- spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter; |
- xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2)); |
- legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter; |
- legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText; |
- } else { |
- yFirstLegendTextPos = topNotUsableSize + config.legendBordersSpaceBefore + (config.legendBordersWidth/2); |
- } |
- if(yAxisUnitHeight>0) { |
- yAxisUnitPosY+=spaceLegendHeight; |
- if(config.legendBorders==true)yLegendBorderPos-=yAxisUnitHeight; |
- yFirstLegendTextPos-=yAxisUnitHeight; |
- } |
- topNotUsableSize += spaceLegendHeight; |
- break; |
- case 1: |
- spaceLegendHeight = legendHeight; |
- xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2; |
- yFirstLegendTextPos = topNotUsableSize + config.legendSpaceBeforeText+config.legendFontSize; |
- if (config.legendBorders == true) { |
- yFirstLegendTextPos += config.legendBordersSpaceBefore+config.legendBordersWidth; |
- yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 ); |
- spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter; |
- xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2)); |
- legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter; |
- legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText; |
- } |
- break; |
- case 2: |
- spaceLegendHeight = legendHeight; |
- xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2; |
- yFirstLegendTextPos = topNotUsableSize + (height - topNotUsableSize - bottomNotUsableHeightWithoutXLabels - spaceLegendHeight) /2 + config.legendSpaceBeforeText+config.legendFontSize; |
- if (config.legendBorders == true) { |
- yFirstLegendTextPos += config.legendBordersSpaceBefore - config.legendBordersSpaceAfter; |
- yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 ); |
- spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter; |
- xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2)); |
- legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter; |
- legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText; |
- } |
- break; |
- case 3: |
- spaceLegendHeight = legendHeight; |
- xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2; |
- availableHeight = height - topNotUsableSize - bottomNotUsableHeightWithoutXLabels; |
- yFirstLegendTextPos = topNotUsableSize + availableHeight - spaceLegendHeight + config.legendSpaceBeforeText+config.legendFontSize; |
- if (config.legendBorders == true) { |
- yFirstLegendTextPos -= (config.legendBordersSpaceAfter+config.legendBordersWidth); |
- yLegendBorderPos = yFirstLegendTextPos - config.legendSpaceBeforeText - config.legendFontSize - (config.legendBordersWidth /2 ); |
- spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter; |
- xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2)); |
- legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter; |
- legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText; |
- } |
- break; |
- default: |
- spaceLegendHeight = legendHeight; |
- yFirstLegendTextPos = height - borderWidth - config.spaceBottom - footNoteHeight - spaceLegendHeight + config.legendSpaceBeforeText + config.legendFontSize; |
- xFirstLegendTextPos = config.spaceLeft + (width - config.spaceLeft - config.spaceRight - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal) / 2; |
- if (config.legendBorders == true) { |
- spaceLegendHeight += 2 * config.legendBordersWidth + config.legendBordersSpaceBefore + config.legendBordersSpaceAfter; |
- yFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceAfter); |
- yLegendBorderPos = Math.floor(height - borderWidth - config.spaceBottom - footNoteHeight - spaceLegendHeight + (config.legendBordersWidth / 2) + config.legendBordersSpaceBefore); |
- xLegendBorderPos = Math.floor(xFirstLegendTextPos - config.legendSpaceLeftText - (config.legendBordersWidth / 2)); |
- legendBorderHeight = Math.ceil(spaceLegendHeight - config.legendBordersWidth) - config.legendBordersSpaceBefore - config.legendBordersSpaceAfter; |
- legendBorderWidth = Math.ceil(nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal)) - config.legendSpaceBetweenTextHorizontal + config.legendBordersWidth + config.legendSpaceRightText + config.legendSpaceLeftText; |
- } |
- xAxisLabelPos -= spaceLegendHeight; |
-// xLabelPos -= spaceLegendHeight; |
- bottomNotUsableHeightWithoutXLabels +=spaceLegendHeight; |
- break; |
- } |
- var fullLegendWidth=config.legendSpaceRightText + nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) - config.legendSpaceBetweenTextHorizontal +config.legendSpaceLeftText; |
- if (config.legendBorders == true) { |
- fullLegendWidth+=2*config.legendBordersWidth+config.legendBordersSpaceLeft+config.legendBordersSpaceRight; |
- } |
- |
- switch (config.legendPosX) { |
- case 0: |
- xFirstLegendTextPos = config.spaceLeft + config.canvasBorders * config.canvasBordersWidth + config.legendSpaceLeftText; |
- if (config.legendBorders == true) { |
- xFirstLegendTextPos += config.legendBordersWidth+config.legendBordersSpaceLeft; |
- xLegendBorderPos = config.spaceLeft + config.canvasBorders * config.canvasBordersWidth + config.legendBordersSpaceLeft; |
- } |
- if(config.legendPosY>=1 && config.legendPosY <=3) { |
- leftNotUsableSize+=fullLegendWidth; |
- yAxisLabelPosLeft+=fullLegendWidth; |
- } |
- break; |
- case 1: |
- xFirstLegendTextPos = leftNotUsableSize + config.legendSpaceLeftText; |
- if (config.legendBorders == true) { |
- xLegendBorderPos = xFirstLegendTextPos; |
- xFirstLegendTextPos += config.legendBordersWidth+config.legendBordersSpaceLeft; |
- } |
- break; |
- case 2: |
- xFirstLegendTextPos = leftNotUsableSize + (width - rightNotUsableSize - leftNotUsableSize)/2 - (config.legendSpaceLeftText-config.legendSpaceRightText) - (nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) - config.legendSpaceBetweenTextHorizontal) / 2; |
- if (config.legendBorders == true) { |
- xFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceRight); |
- xLegendBorderPos = xFirstLegendTextPos - config.legendBordersWidth/2 - config.legendSpaceLeftText ; |
- } |
- break; |
- case 3: |
- |
- xFirstLegendTextPos = width - rightNotUsableSize - config.legendSpaceRightText - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal / 2; |
- if (config.legendBorders == true) { |
- xFirstLegendTextPos -= (config.legendBordersWidth + config.legendBordersSpaceRight); |
- xLegendBorderPos = xFirstLegendTextPos - config.legendBordersWidth/2 - config.legendSpaceLeftText ; |
- } |
- break; |
- case 4: |
- xFirstLegendTextPos = width - config.spaceRight - config.canvasBorders * config.canvasBordersWidth - config.legendSpaceRightText - nbLegendCols * (widestLegend + config.legendSpaceBetweenTextHorizontal) + config.legendSpaceBetweenTextHorizontal / 2; |
- if (config.legendBorders == true) { |
- xFirstLegendTextPos -= (config.legendBordersWidth+config.legendBordersSpaceRight); |
- xLegendBorderPos = xFirstLegendTextPos - config.legendBordersSpaceLeft - config.legendBordersWidth/2; |
- } |
- if(config.legendPosY>=1 && config.legendPosY <=3) { |
- rightNotUsableSize+=fullLegendWidth; |
- yAxisLabelPosRight-=fullLegendWidth; |
- } |
- break; |
- |
- default: |
- break; |
- } |
- if(config.legendBorders==true) { |
- yLegendBorderPos+=config.legendYPadding; |
- xLegendBorderPos+=config.legendXPadding; |
- |
- } |
- yFirstLegendTextPos+=config.legendYPadding; |
- xFirstLegendTextPos+=config.legendXPadding; |
- |
- } |
- } |
- } |
- xLabelWidth = 0; |
- bottomNotUsableHeightWithXLabels = bottomNotUsableHeightWithoutXLabels; |
- if (drawAxis && (config.xAxisBottom || config.xAxisTop)) { |
- if (reverseAxis == false) { |
- var widestLabel = widestXLabel; |
- var highestLabel = highestXLabel; |
- nblab = data.labels.length; |
- } else { |
- var widestLabel = widestYLabel; |
- var highestLabel = highestYLabel; |
- nblab = ylabels.length; |
- } |
- if (config.rotateLabels == "smart") { |
- rotateLabels = 0; |
- if ((availableWidth + config.xAxisSpaceBetweenLabels) / nblab < (widestLabel + config.xAxisSpaceBetweenLabels)) { |
- rotateLabels = 45; |
- if (availableWidth / nblab < Math.abs(Math.cos(rotateLabels * Math.PI / 180) * widestLabel)) { |
- rotateLabels = 90; |
- } |
- } |
- } else { |
- rotateLabels = config.rotateLabels |
- if (rotateLabels < 0) rotateLabels = 0; |
- if (rotateLabels > 180) rotateLabels = 180; |
- } |
- if (rotateLabels > 90) rotateLabels += 180; |
- xLabelHeight = Math.abs(Math.sin(rotateLabels * Math.PI / 180) * widestLabel) + Math.abs(Math.sin((rotateLabels + 90) * Math.PI / 180) * highestLabel) + config.xAxisSpaceBefore + config.xAxisSpaceAfter; |
- xLabelPos = height - borderWidth - config.spaceBottom - footNoteHeight - xAxisLabelHeight - (xLabelHeight - config.xAxisSpaceBefore) - config.graphSpaceAfter; |
- xLabelWidth = Math.abs(Math.cos(rotateLabels * Math.PI / 180) * widestLabel) + Math.abs(Math.cos((rotateLabels + 90) * Math.PI / 180) * highestLabel); |
- leftNotUsableSize = Max([leftNotUsableSize, borderWidth + config.spaceLeft + xLabelWidth / 2]); |
- rightNotUsableSize = Max([rightNotUsableSize, borderWidth + config.spaceRight + xLabelWidth / 2]); |
- availableWidth = width - leftNotUsableSize - rightNotUsableSize; |
- if (config.legend && config.xAxisBottom && config.legendPosY==4) { |
- xLabelPos-=spaceLegendHeight; |
- } |
- bottomNotUsableHeightWithXLabels = bottomNotUsableHeightWithoutXLabels + xLabelHeight ; |
- } else { |
- availableWidth = width - leftNotUsableSize - rightNotUsableSize; |
- } |
- |
- availableHeight = height - topNotUsableSize - bottomNotUsableHeightWithXLabels; |
- |
- // ----------------------- DRAW EXTERNAL ELEMENTS ------------------------------------------------- |
- dispCrossImage(ctx, config, width / 2, height / 2, width / 2, height / 2, false, data, -1, -1); |
- if (ylabels != "nihil") { |
- // Draw Borders |
- if (borderWidth > 0) { |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.lineWidth = 2 * borderWidth; |
- ctx.strokeStyle = config.canvasBordersColor; |
- ctx.moveTo(0, 0); |
- ctx.lineTo(0, height); |
- ctx.lineTo(width, height); |
- ctx.lineTo(width, 0); |
- ctx.lineTo(0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- // Draw Graph Title |
- if (graphTitleHeight > 0) { |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.graphTitleFontStyle + " " + config.graphTitleFontSize + "px " + config.graphTitleFontFamily; |
- ctx.fillStyle = config.graphTitleFontColor; |
- ctx.textAlign = "center"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(config.spaceLeft + (width - config.spaceLeft - config.spaceRight) / 2, graphTitlePosY); |
- ctx.fillText(config.graphTitle, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- // Draw Graph Sub-Title |
- if (graphSubTitleHeight > 0) { |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.graphSubTitleFontStyle + " " + config.graphSubTitleFontSize + "px " + config.graphSubTitleFontFamily; |
- ctx.fillStyle = config.graphSubTitleFontColor; |
- ctx.textAlign = "center"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(config.spaceLeft + (width - config.spaceLeft - config.spaceRight) / 2, graphSubTitlePosY); |
- ctx.fillText(config.graphSubTitle, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- // Draw Y Axis Unit |
- if (yAxisUnitHeight > 0) { |
- if (config.yAxisLeft) { |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.yAxisUnitFontStyle + " " + config.yAxisUnitFontSize + "px " + config.yAxisUnitFontFamily; |
- ctx.fillStyle = config.yAxisUnitFontColor; |
- ctx.textAlign = "center"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(leftNotUsableSize, yAxisUnitPosY); |
- ctx.fillText(config.yAxisUnit, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- if (config.yAxisRight) { |
- if (config.yAxisUnit2 == '') config.yAxisUnit2 = config.yAxisUnit; |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.yAxisUnitFontStyle + " " + config.yAxisUnitFontSize + "px " + config.yAxisUnitFontFamily; |
- ctx.fillStyle = config.yAxisUnitFontColor; |
- ctx.textAlign = "center"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(width - rightNotUsableSize, yAxisUnitPosY); |
- ctx.fillText(config.yAxisUnit2, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- } |
- // Draw Y Axis Label |
- if (yAxisLabelWidth > 0) { |
- if (config.yAxisLeft) { |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.yAxisFontStyle + " " + config.yAxisFontSize + "px " + config.yAxisFontFamily; |
- ctx.fillStyle = config.yAxisFontColor; |
- ctx.textAlign = "center"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(yAxisLabelPosLeft, topNotUsableSize + (availableHeight / 2)); |
- ctx.rotate(-(90 * (Math.PI / 180))); |
- ctx.fillText(config.yAxisLabel, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- if (config.yAxisRight) { |
- if (config.yAxisLabel2 == '') config.yAxisLabel2 = config.yAxisLabel; |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.yAxisFontStyle + " " + config.yAxisFontSize + "px " + config.yAxisFontFamily; |
- ctx.fillStyle = config.yAxisFontColor; |
- ctx.textAlign = "center"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(yAxisLabelPosRight, topNotUsableSize + (availableHeight / 2)); |
- ctx.rotate(+(90 * (Math.PI / 180))); |
- ctx.fillText(config.yAxisLabel2, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- } |
- // Draw X Axis Label |
- if (xAxisLabelHeight > 0) { |
- if (config.xAxisBottom) { |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.xAxisFontStyle + " " + config.xAxisFontSize + "px " + config.xAxisFontFamily; |
- ctx.fillStyle = config.xAxisFontColor; |
- ctx.textAlign = "center"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(leftNotUsableSize + (availableWidth / 2), xAxisLabelPos); |
- ctx.fillText(config.xAxisLabel, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- } |
- // Draw Legend |
- |
- if (nbeltLegend > 1 || (nbeltLegend == 1 && config.showSingleLegend)) { |
- var legendMsr={dispLegend : true, xLegendBorderPos : xLegendBorderPos, |
- yLegendBorderPos : yLegendBorderPos, legendBorderWidth : legendBorderWidth, legendBorderHeight : legendBorderHeight, |
- nbLegendCols: nbLegendCols, xFirstLegendTextPos : xFirstLegendTextPos , yFirstLegendTextPos : yFirstLegendTextPos, |
- drawLegendOnData : drawLegendOnData, reverseLegend : reverseLegend, legendBox : legendBox, widestLegend : widestLegend }; |
- if(config.legendPosY==0 || config.legendPosY==4) { |
- drawLegend(legendMsr,data,config,ctx,typegraph); |
- var legendMsr={dispLegend : false}; |
- } |
- } else { |
- var legendMsr={dispLegend : false }; |
- } |
- // Draw FootNote |
- if (config.footNote.trim() != "") { |
- ctx.save(); |
- ctx.font = config.footNoteFontStyle + " " + config.footNoteFontSize + "px " + config.footNoteFontFamily; |
- ctx.fillStyle = config.footNoteFontColor; |
- ctx.textAlign = "center"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(leftNotUsableSize + (availableWidth / 2), footNotePosY); |
- ctx.fillText(config.footNote, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- } |
- clrx = leftNotUsableSize; |
- clrwidth = availableWidth; |
- clry = topNotUsableSize; |
- clrheight = availableHeight; |
- return { |
- leftNotUsableSize: leftNotUsableSize, |
- rightNotUsableSize: rightNotUsableSize, |
- availableWidth: availableWidth, |
- topNotUsableSize: topNotUsableSize, |
- bottomNotUsableHeightWithoutXLabels: bottomNotUsableHeightWithoutXLabels, |
- bottomNotUsableHeightWithXLabels: bottomNotUsableHeightWithXLabels, |
- availableHeight: availableHeight, |
- widestXLabel: widestXLabel, |
- highestXLabel: highestXLabel, |
- widestYLabel: widestYLabel, |
- widestYLabel2: widestYLabel2, |
- highestYLabel: highestYLabel, |
- rotateLabels: rotateLabels, |
- xLabelPos: xLabelPos, |
- clrx: clrx, |
- clry: clry, |
- clrwidth: clrwidth, |
- clrheight: clrheight, |
- legendMsr : legendMsr |
- }; |
- }; |
- // Function for additionalLine (BarLine|Line) |
- function drawLinesDataset(axis, animPc, data, config, ctx, offsets, vars) { |
- var xAxisPosY = vars.xAxisPosY; |
- var yAxisPosX = vars.yAxisPosX; |
- var valueHop = vars.valueHop; |
- var nbValueHop = vars.nbValueHop; |
- var scaleHop = vars.scaleHop; |
- var zeroY = vars.zeroY; |
- var calculatedScale = vars.calculatedScale; |
- var logarithmic = vars.logarithmic; |
- var currentAnimPc = animationCorrection(animPc, data, config, 0, 0, 0); |
- var totvalue = new Array(); |
- var maxvalue = new Array(); |
- var lmaxvalue = new Array(); |
- var lminvalue = new Array(); |
- for (var i = 0; i < data.datasets.length; i++) { |
- lmaxvalue[i] = -999999999; |
- lminvalue[i] = 999999999; |
- if ((axis == 2 && data.datasets[i].axis == 2) || (axis != 2 && data.datasets[i].axis != 2)) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- totvalue[j] = 0; |
- maxvalue[j] = -999999999; |
- } |
- } |
- } |
- currentAnimPc.mainVal = 1; |
- for (var i = 0; i < data.datasets.length; i++) { |
- if ((axis == 2 && data.datasets[i].axis == 2) || (axis != 2 && data.datasets[i].axis != 2)) { |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- totvalue[j] += data.datasets[i].data[j]; |
- maxvalue[j] = Max([maxvalue[j], data.datasets[i].data[j]]); |
- lmaxvalue[i] = Max([lmaxvalue[i], yPos(i, j)]); |
- lminvalue[i] = Min([lminvalue[i], yPos(i, j)]); |
- } |
- } |
- } |
- for (var i = 0; i < data.datasets.length; i++) { |
- if ((axis == 2 && data.datasets[i].axis == 2) || (axis != 2 && data.datasets[i].axis != 2)) { |
- var prevpt = -1; |
- var frstpt = -1; |
- if (typeof data.datasets[i].strokeColor == "function") { |
- ctx.strokeStyle = data.datasets[i].strokeColor("STROKECOLOR", data, config, i, -1, animPc, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i])); |
- } else if (typeof data.datasets[i].strokeColor == "string") { |
- ctx.strokeStyle = data.datasets[i].strokeColor; |
- } else ctx.strokeStyle = config.defaultStrokeColor; |
- ctx.lineWidth = config.datasetStrokeWidth; |
- ctx.beginPath(); |
- var prevAnimPc; |
- var prevXpos; |
- prevAnimPc = 0; |
- prevnotempty = 0; |
- for (var j = 0; j < data.datasets[i].data.length; j++) { |
- var xposj = xPos(i, j, data); |
- currentAnimPc = animationCorrection(animPc, data, config, i, j, 0); |
- if (currentAnimPc.mainVal == 0 && prevAnimPc > 0) { |
- ctx.stroke(); |
- ctx.strokeStyle = "rgba(0,0,0,0)"; |
- // ctx.lineWidth =0.01; |
- ctx.lineTo(prevXpos, xAxisPosY - zeroY); |
- } |
- prevAnimPc = currentAnimPc.mainVal; |
- if (currentAnimPc.mainVal >= 1) { |
- if (typeof(data.datasets[i].title) == "string") lgtxt = data.datasets[i].title.trim(); |
- else lgtxt = ""; |
- } |
- if (!(typeof(data.datasets[i].data[j]) == 'undefined')) { |
- prevXpos = xPos(i, j, data); |
- if (prevpt == -1) { |
- ctx.moveTo(xposj, yPos(i, j)); |
- frstpt = j; |
- } else { |
- if (config.bezierCurve) { |
- ctx.bezierCurveTo(xPos(i, j - (j - prevpt) / 2, data), yPos(i, prevpt), xPos(i, j - (j - prevpt) / 2, data), yPos(i, j), xPos(i, j, data), yPos(i, j)); |
- } else { |
- ctx.lineTo(xPos(i, j, data), yPos(i, j)); |
- } |
- } |
- if ((typeof(data.datasets[i].data[j + 1]) !== 'undefined') || (true == config.extrapolateMissingData)) { |
- if (currentAnimPc.subVal > 0) { |
- // next not missing value |
- nxtnotmiss = -1; |
- for (t = j + 1; t < data.datasets[i].data["length"] && nxtnotmiss == -1; t++) { |
- if (!(typeof(data.datasets[i].data[t]) == 'undefined')) nxtnotmiss = t; |
- } |
- if (nxtnotmiss != -1) { |
- prevXpos = xPos(i, j + currentAnimPc.subVal, data); |
- if (config.bezierCurve) { |
- ctx.bezierCurveTo(xPos(i, j + currentAnimPc.subVal / 2, data), yPos(i, j), xPos(i, j + currentAnimPc.subVal / 2, data), yPos(i, nxtnotmiss), xPos(i, j + currentAnimPc.subVal, data), yPos(i, nxtnotmiss)); |
- } else { |
- ctx.lineTo(xPos(i, j + currentAnimPc.subVal, data), yPos(i, j + 1)); |
- } |
- } |
- } |
- prevpt = j; |
- if (animPc >= 1) { |
- if (i == 0) divprev = data.datasets[i].data[j]; |
- else divprev = data.datasets[i].data[j] - data.datasets[i - 1].data[j]; |
- if (i == data.datasets.length - 1) divnext = data.datasets[i].data[j]; |
- else divnext = data.datasets[i].data[j] - data.datasets[i + 1].data[j]; |
- lgtxt2 = ""; |
- if (typeof data.datasets[i].xPos != "undefined") { |
- if (!(typeof data.datasets[i].xPos[j] == "undefined")) lgtxt2 = data.datasets[i].xPos[j]; |
- } |
- if (lgtxt2 == "" && !(typeof(data.labels[j]) == "undefined")) lgtxt2 = data.labels[j]; |
- if (typeof lgtxt2 == "string") lgtxt2 = lgtxt2.trim(); |
- jsGraphAnnotate[ctx.ChartNewId][jsGraphAnnotate[ctx.ChartNewId].length] = ["POINT", xPos(i, j, data), yPos(i, j), lgtxt, lgtxt2, 1 * data.datasets[i].data[j], divprev, divnext, maxvalue[j], totvalue[j], i, j]; |
- if (config.inGraphDataShow) { |
- ctx.save(); |
- ctx.textAlign = config.inGraphDataAlign; |
- ctx.textBaseline = config.inGraphDataVAlign; |
- ctx.font = config.inGraphDataFontStyle + ' ' + config.inGraphDataFontSize + 'px ' + config.inGraphDataFontFamily; |
- ctx.fillStyle = config.inGraphDataFontColor; |
- var dotX = yAxisPosX + (valueHop * k), |
- dotY = xAxisPosY - currentAnimPc.mainVal * (calculateOffset(logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)), |
- paddingTextX = config.inGraphDataPaddingX, |
- paddingTextY = config.inGraphDataPaddingY; |
- var dispString = tmplbis(config.inGraphDataTmpl, { |
- config: config, |
- v1: fmtChartJS(config, lgtxt, config.fmtV1), |
- v2: fmtChartJS(config, lgtxt2, config.fmtV2), |
- v3: fmtChartJS(config, 1 * data.datasets[i].data[j], config.fmtV3), |
- v4: fmtChartJS(config, divprev, config.fmtV4), |
- v5: fmtChartJS(config, divnext, config.fmtV5), |
- v6: fmtChartJS(config, maxvalue[j], config.fmtV6), |
- v7: fmtChartJS(config, totvalue[j], config.fmtV7), |
- v8: roundToWithThousands(config, fmtChartJS(config, 100 * data.datasets[i].data[j] / totvalue[j], config.fmtV8), config.roundPct), |
- v9: fmtChartJS(config, yAxisPosX + (valueHop * k), config.fmtV9), |
- v10: fmtChartJS(config, xAxisPosY - (calculateOffset(logarithmic, data.datasets[i].data[j], calculatedScale, scaleHop)), config.fmtV10), |
- v11: fmtChartJS(config, i, config.fmtV11), |
- v12: fmtChartJS(config, j, config.fmtV12), |
- data: data |
- }); |
- ctx.translate(xPos(i, j, data) + paddingTextX, yPos(i, j) - paddingTextY); |
- ctx.rotate(config.inGraphDataRotate * (Math.PI / 180)); |
- ctx.fillTextMultiLine(dispString, 0, 0, ctx.textBaseline, config.inGraphDataFontSize); |
- ctx.restore(); |
- } |
- } |
- } |
- } else { |
- if (false == config.extrapolateMissingData) { |
- ctx.stroke(); |
- if (config.datasetFill) { |
- ctx.lineTo(prevXpos, xAxisPosY - zeroY); |
- ctx.lineTo(xPos(i, frstpt, data), xAxisPosY - zeroY); |
- ctx.lineTo(xPos(i, frstpt, data), yPos(i, frstpt)); |
- ctx.closePath(); |
- if (typeof data.datasets[i].fillColor == "function") ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, -1, currentAnimPc.mainVal, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i])); |
- else if (typeof data.datasets[i].fillColor == "string") ctx.fillStyle = data.datasets[i].fillColor; |
- else ctx.fillStyle = config.defaultFillColor; |
- ctx.fill(); |
- } |
- ctx.beginPath(); |
- prevpt = -1; |
- frstpt = -1; |
- prevAnimPc = 0; |
- prevnotempty = 0; |
- } else { |
- if (currentAnimPc.subVal > 0) { |
- nxtnotmiss = -1; |
- for (t = j + 1; t < data.datasets[i].data["length"] && nxtnotmiss == -1; t++) { |
- if (!(typeof(data.datasets[i].data[t]) == 'undefined')) nxtnotmiss = t; |
- } |
- if ((typeof(data.datasets[i].data[j]) !== 'undefined') || (true == config.extrapolateMissingData)) { |
- if (nxtnotmiss != -1) { |
- prevXpos = xPos(i, j + currentAnimPc.subVal, data); |
- if (config.bezierCurve) { |
- ctx.bezierCurveTo(xPos(i, prevpt + (j + currentAnimPc.subVal - prevpt) / 2, data), yPos(i, prevpt), xPos(i, prevpt + (j + currentAnimPc.subVal - prevpt) / 2, data), yPos(i, nxtnotmiss), xPos(i, j + currentAnimPc.subVal, data), yPos(i, nxtnotmiss)); |
- } else { |
- ctx.lineTo(xPos(i, j + currentAnimPc.subVal, data), yPos(i, j + 1)); |
- } |
- } |
- } |
- } |
- } |
- } |
- } |
- ctx.stroke(); |
- if (config.datasetFill) { |
- // ctx.lineTo(yAxisPosX + (valueHop * (data.datasets[i].data.length - 1)), xAxisPosY - zeroY); |
- ctx.lineTo(prevXpos, xAxisPosY - zeroY); |
- ctx.lineTo(xPos(i, frstpt, data), xAxisPosY - zeroY); |
- ctx.lineTo(xPos(i, frstpt, data), yPos(i, frstpt)); |
- ctx.closePath(); |
- if (typeof data.datasets[i].fillColor == "function") { ctx.fillStyle = data.datasets[i].fillColor("FILLCOLOR", data, config, i, -1, currentAnimPc.mainVal, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i])); } |
- else if (typeof data.datasets[i].fillColor == "string") ctx.fillStyle = data.datasets[i].fillColor; |
- else ctx.fillStyle = config.defaultFillColor; |
- ctx.fill(); |
- } else { |
- ctx.closePath(); |
- } |
- if (config.pointDot) { |
- if (typeof data.datasets[i].pointColor == "function") ctx.fillStyle = data.datasets[i].pointColor("POINTCOLOR", data, config, i, -1, animPc, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i])); |
- else ctx.fillStyle = data.datasets[i].pointColor; |
- if (typeof data.datasets[i].pointStrokeColor == "function") ctx.strokeStyle = data.datasets[i].pointStrokeColor("POINTSTROKECOLOR", data, config, i, -1, animPc, -1, "Line", ctx, yAxisPosX, lmaxvalue[i], yAxisPosX + valueHop * (data.datasets[i].data.length - 1), lmaxvalue[i] - ((config.animationLeftToRight) ? 1 : 1*currentAnimPc.mainVal) * (lmaxvalue[i] - lminvalue[i])); |
- else ctx.strokeStyle = data.datasets[i].pointStrokeColor; |
- ctx.lineWidth = config.pointDotStrokeWidth; |
- for (var k = 0; k < data.datasets[i].data.length; k++) { |
- if (!(typeof(data.datasets[i].data[k]) == 'undefined')) { |
- var currentAnimPc = animationCorrection(animPc, data, config, i, k, 0); |
- if (currentAnimPc.mainVal > 0 || !config.animationLeftToRight) { |
- ctx.beginPath(); |
- ctx.arc(xPos(i, k, data), yPos(i, k), config.pointDotRadius, 0, Math.PI * 2, true); |
- ctx.fill(); |
- ctx.stroke(); |
- } |
- } |
- } |
- } |
- } |
- }; |
- |
- function yPos(dataSet, iteration) { |
- return xAxisPosY - zeroY - currentAnimPc.mainVal * (calculateOffset(logarithmic, data.datasets[dataSet].data[iteration], calculatedScale, scaleHop) - zeroY); |
- }; |
- |
- function xPos(ival, iteration, data) { |
- if (typeof data.datasets[ival].xPos == "object") { |
- if (!(typeof data.datasets[ival].xPos[Math.floor(iteration + 0.0001)] == "undefined")) { |
- var width = valueHop * nbValueHop; |
- var deb = (typeof data.xBegin != "undefined") ? data.xBegin : 1 * data.labels[0]; |
- var fin = (typeof data.xEnd != "undefined") ? data.xEnd : 1 * data.labels[data.labels.length - 1]; |
- if (fin <= deb) fin = deb + 100; |
- if (1 * data.datasets[ival].xPos[Math.floor(iteration + 0.0001)] >= deb && data.datasets[ival].xPos[Math.floor(iteration + 0.0001)] <= fin) { |
- var p1 = yAxisPosX + width * ((1 * data.datasets[ival].xPos[Math.floor(iteration + 0.0001)] - deb) / (fin - deb)); |
- var p2 = p1; |
- if (Math.abs(iteration - Math.floor(iteration + 0.0001)) > 0.0001) { |
- var tt = iteration + Math.floor(iteration + 0.0001); |
- var p2 = xPos(ival, Math.ceil(iteration - 0.0001), data); |
- } |
- return p1 + (iteration - Math.floor(iteration + 0.0001)) * (p2 - p1); |
- } |
- } |
- } |
- return yAxisPosX + (valueHop * iteration); |
- }; |
- }; |
- |
- function log10(val) { |
- return Math.log(val) / Math.LN10; |
- }; |
- |
- function setRect(ctx, config) { |
- if (config.clearRect) { |
- if (!config.multiGraph) { |
- clear(ctx); |
- ctx.clearRect(0, 0, width, height); |
- } |
- } else { |
- clear(ctx); |
- ctx.clearRect(0, 0, width, height); |
- |
- ctx.fillStyle = config.savePngBackgroundColor; |
- ctx.strokeStyle = config.savePngBackgroundColor; |
- ctx.beginPath(); |
- ctx.moveTo(0, 0); |
- ctx.lineTo(0, ctx.canvas.height); |
- ctx.lineTo(ctx.canvas.width, ctx.canvas.height); |
- ctx.lineTo(ctx.canvas.width, 0); |
- ctx.lineTo(0, 0); |
- ctx.stroke(); |
- ctx.fill(); |
- } |
- }; |
- |
- function defMouse(ctx, data, config) { |
- if (config.annotateDisplay == true) { |
- if (cursorDivCreated == false) oCursor = new makeCursorObj('divCursor'); |
- if (isIE() < 9 && isIE() != false) ctx.canvas.attachEvent("on" + config.annotateFunction.split(' ')[0], function(event) { |
- if ((config.annotateFunction.split(' ')[1] == "left" && event.which == 1) || |
- (config.annotateFunction.split(' ')[1] == "middle" && event.which == 2) || |
- (config.annotateFunction.split(' ')[1] == "right" && event.which == 3) || |
- (typeof(config.annotateFunction.split(' ')[1]) != "string")) doMouseAction(config, ctx, event, data, "annotate", config.mouseDownRight) |
- }); |
- else ctx.canvas.addEventListener(config.annotateFunction.split(' ')[0], function(event) { |
- if ((config.annotateFunction.split(' ')[1] == "left" && event.which == 1) || |
- (config.annotateFunction.split(' ')[1] == "middle" && event.which == 2) || |
- (config.annotateFunction.split(' ')[1] == "right" && event.which == 3) || |
- (typeof(config.annotateFunction.split(' ')[1]) != "string")) doMouseAction(config, ctx, event, data, "annotate", config.mouseDownRight) |
- }, false); |
- } |
- if (config.savePng) { |
- if (isIE() < 9 && isIE() != false) ctx.canvas.attachEvent("on" + config.savePngFunction.split(' ')[0], function(event) { |
- if ((config.savePngFunction.split(' ')[1] == "left" && event.which == 1) || |
- (config.savePngFunction.split(' ')[1] == "middle" && event.which == 2) || |
- (config.savePngFunction.split(' ')[1] == "right" && event.which == 3) || |
- (typeof(config.savePngFunction.split(' ')[1]) != "string")) saveCanvas(ctx, data, config); |
- }); |
- else ctx.canvas.addEventListener(config.savePngFunction.split(' ')[0], function(event) { |
- if ((config.savePngFunction.split(' ')[1] == "left" && event.which == 1) || |
- (config.savePngFunction.split(' ')[1] == "middle" && event.which == 2) || |
- (config.savePngFunction.split(' ')[1] == "right" && event.which == 3) || |
- (typeof(config.savePngFunction.split(' ')[1]) != "string")) saveCanvas(ctx, data, config); |
- }, false); |
- } |
- |
- if (isIE() < 9 && isIE() != false) ctx.canvas.attachEvent("onmousewheel", function(event) { |
- if (cursorDivCreated) document.getElementById('divCursor').style.display = 'none'; |
- }); |
- else ctx.canvas.addEventListener("DOMMouseScroll", function(event) { |
- if (cursorDivCreated) document.getElementById('divCursor').style.display = 'none'; |
- }, false); |
- |
- |
- |
- function add_event_listener(type, func, chk) |
- { |
- if(typeof func != 'function') |
- return; |
- |
- function do_func(event) { |
- if (chk == null || chk(event)) doMouseAction(config,ctx,event,data,"mouseaction",func); |
- }; |
- |
- var hash = type+' '+func.name; |
- if(hash in ctx._eventListeners) { |
- if(ctx.canvas.removeEventListener) |
- ctx.canvas.removeEventListener(type, ctx._eventListeners[hash]); |
- else if(ctx.canvas.detachEvent) |
- ctx.canvas.detachEvent(type, ctx._eventListeners[hash]); |
- } |
- |
- ctx._eventListeners[hash] = do_func; |
- |
- if(ctx.canvas.addEventListener) { |
- if(type=="mousewheel") type="DOMMouseScroll"; |
- ctx.canvas.addEventListener(type, do_func, false); |
- } else if(ctx.canvas.attachEvent) { |
- ctx.canvas.attachEvent("on"+type, do_func); |
- } |
- }; |
- |
- add_event_listener("mousedown", config.mouseDownLeft, function(e) { return e.which == 1; }); |
- add_event_listener("mousedown", config.mouseDownMiddle, function(e) { return e.which == 2; }); |
- add_event_listener("mousedown", config.mouseDownRight, function(e) { return e.which == 3; }); |
- add_event_listener("mousemove", config.mouseMove); |
- add_event_listener("mouseout", config.mouseOut); |
- add_event_listener("mousewheel", config.mouseWheel); |
- }; |
-}; |
- |
-function animationCorrection(animationValue, data, config, vdata, vsubdata, addone) { |
- var animValue = animationValue; |
- var animSubValue = 0; |
- if (vsubdata != -1) { |
- if (animValue < 1 && (vdata < (config.animationStartWithDataset - 1) && (config.animationStartWithDataset - 1) != -1)) { |
- animValue = 1; |
- } |
- if (animValue < 1 && (vsubdata < (config.animationStartWithData - 1) && (config.animationStartWithData - 1) != -1)) { |
- animValue = 1; |
- } |
- var totreat = 1; |
- var newAnimationValue = animationValue; |
- if (animValue < 1 && config.animationByDataset) { |
- animValue = 0; |
- totreat = 0; |
- var startDataset = (config.animationStartWithDataset - 1); |
- if ((config.animationStartWithDataset - 1) == -1) startDataset = 0 |
- var nbstepsperdatasets = config.animationSteps / (data.datasets.length - startDataset); |
- if (animationValue >= (vdata - startDataset + 1) * nbstepsperdatasets / config.animationSteps) animValue = 1; |
- else if (animationValue >= (vdata - startDataset) * nbstepsperdatasets / config.animationSteps) { |
- var redAnimationValue = animationValue - (vdata - startDataset) * nbstepsperdatasets / config.animationSteps; |
- if (!config.animationLeftToRight) { |
- animValue = redAnimationValue * (data.datasets.length - startDataset); |
- } else { |
- newAnimationValue = redAnimationValue * (data.datasets.length - startDataset); |
- } |
- totreat = 1; |
- } |
- } |
- if (totreat == 1 && animValue < 1 && config.animationLeftToRight) { |
- animValue = 0; |
- var startSub = (config.animationStartWithData - 1); |
- if ((config.animationStartWithData - 1) == -1) startSub = 0 |
- var nbstepspervalue = config.animationSteps / (data.datasets[vdata].data.length - startSub - 1 + addone); |
- if (newAnimationValue >= (vsubdata - startSub) * nbstepspervalue / config.animationSteps) { |
- animValue = 1; |
- if (newAnimationValue <= (vsubdata + 1 - startSub) * nbstepspervalue / config.animationSteps) { |
- animSubValue = (data.datasets[vdata].data.length - startSub - 1) * (newAnimationValue - ((vsubdata - startSub) * nbstepspervalue / config.animationSteps)); |
- } |
- } |
- } |
- } else { |
- if (animValue < 1 && (vdata < (config.animationStartWithData - 1))) { |
- animValue = 1; |
- } |
- } |
- return { |
- mainVal: animValue, |
- subVal: animSubValue, |
- animVal: animValue + animSubValue |
- }; |
-}; |
- |
- |
-function drawLegend(legendMsr,data,config,ctx,typegraph) { |
- if (config.legendBorders == true) { |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.lineWidth = config.legendBordersWidth; |
- ctx.strokeStyle = config.legendBordersColors; |
- ctx.moveTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos); |
- ctx.lineTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos + legendMsr.legendBorderHeight); |
- ctx.lineTo(legendMsr.xLegendBorderPos + legendMsr.legendBorderWidth, legendMsr.yLegendBorderPos + legendMsr.legendBorderHeight); |
- ctx.lineTo(legendMsr.xLegendBorderPos + legendMsr.legendBorderWidth, legendMsr.yLegendBorderPos); |
- ctx.lineTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos); |
- ctx.lineTo(legendMsr.xLegendBorderPos + legendMsr.legendBorderWidth, legendMsr.yLegendBorderPos); |
- ctx.lineTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos); |
- ctx.lineTo(legendMsr.xLegendBorderPos, legendMsr.yLegendBorderPos + legendMsr.legendBorderHeight); |
- ctx.stroke(); |
- ctx.closePath(); |
- ctx.fillStyle = "rgba(0,0,0,0)"; // config.legendFillColor; |
- ctx.fillStyle = config.legendFillColor; |
- ctx.fill(); |
- ctx.restore(); |
- } |
- nbcols = legendMsr.nbLegendCols - 1; |
- ypos = legendMsr.yFirstLegendTextPos - (config.legendFontSize + config.legendSpaceBetweenTextVertical); |
- xpos = 0; |
- if (legendMsr.drawLegendOnData) fromi = data.datasets.length; |
- else fromi = data.length; |
- for (var i = fromi - 1; i >= 0; i--) { |
- orderi = i; |
- if (legendMsr.reverseLegend) { |
- if (legendMsr.drawLegendOnData) orderi = data.datasets.length - i - 1; |
- else orderi = data.length - i - 1; |
- } |
- if (legendMsr.drawLegendOnData) tpof = typeof(data.datasets[orderi].title); |
- else tpof = typeof(data[orderi].title) |
- if (tpof == "string") { |
- if (legendMsr.drawLegendOnData) lgtxt = fmtChartJS(config, data.datasets[orderi].title, config.fmtLegend).trim(); |
- else lgtxt = fmtChartJS(config, data[orderi].title, config.fmtLegend).trim(); |
- if (lgtxt != "") { |
- nbcols++; |
- if (nbcols == legendMsr.nbLegendCols) { |
- nbcols = 0; |
- xpos = legendMsr.xFirstLegendTextPos; |
- ypos += config.legendFontSize + config.legendSpaceBetweenTextVertical; |
- } else { |
- xpos += legendMsr.widestLegend + config.legendSpaceBetweenTextHorizontal; |
- } |
- ctx.save(); |
- ctx.beginPath(); |
- if (legendMsr.drawLegendOnData) { |
- if (typeof data.datasets[orderi].strokeColor == "function") ctx.strokeStyle = data.datasets[orderi].strokeColor("STROKECOLOR", data, config, orderi, -1, 1, -1, typegraph, ctx, -1, -1, -1, -1); |
- else if (typeof data.datasets[orderi].strokeColor == "string") ctx.strokeStyle = data.datasets[orderi].strokeColor; |
- else ctx.strokeStyle = config.defaultStrokeColor; |
- } else { |
- if (typeof data[orderi].color == "function") ctx.strokeStyle = data[orderi].color("COLOR", data, config, orderi, -1, 1, data[orderi].value, typegraph, ctx, 1, 1, 1, 1); |
- else if (typeof data[orderi].color == "string") ctx.strokeStyle = data[orderi].color; |
- else ctx.strokeStyle = config.defaultStrokeColor; |
- } |
- if (legendMsr.legendBox) { |
- ctx.lineWidth = 1; |
- ctx.moveTo(xpos, ypos); |
- ctx.lineTo(xpos + config.legendBlockSize, ypos); |
- ctx.lineTo(xpos + config.legendBlockSize, ypos - config.legendFontSize); |
- ctx.lineTo(xpos, ypos - config.legendFontSize); |
- ctx.lineTo(xpos, ypos); |
- ctx.closePath(); |
- if (legendMsr.drawLegendOnData) { |
- if (typeof data.datasets[orderi].fillColor == "function") ctx.fillStyle = data.datasets[orderi].fillColor("LEGENDFILLCOLOR", data, config, orderi, -1, 1, -1, typegraph, ctx, xpos, ypos, xpos + config.legendBlockSize, ypos - config.legendFontSize); |
- else if (typeof data.datasets[orderi].fillColor == "string") ctx.fillStyle = data.datasets[orderi].fillColor; |
- else ctx.fillStyle = config.defaultFillColor; |
- } else { |
- if (typeof data[orderi].color == "function") ctx.fillStyle = data[orderi].color("LEGENDFILLCOLOR", data, config, orderi, -1, 1, -1, typegraph, ctx, xpos, ypos - config.legendFontSize, xpos + config.legendBlockSize, ypos); |
- else if (typeof data[orderi].color == "string") ctx.fillStyle = data[orderi].color; |
- else ctx.fillStyle = config.defaultFillColor; |
- } |
- ctx.fill(); |
- } else { |
- ctx.lineWidth = config.legendColorIndicatorStrokeWidth ? |
- config.legendColorIndicatorStrokeWidth : config.datasetStrokeWidth; |
- if (config.legendColorIndicatorStrokeWidth && config.legendColorIndicatorStrokeWidth > config.legendFontSize) { |
- ctx.lineWidth = config.legendFontSize; |
- } |
- ctx.moveTo(xpos + 2, ypos - (config.legendFontSize / 2)); |
- ctx.lineTo(xpos + 2 + config.legendBlockSize, ypos - (config.legendFontSize / 2)); |
- } |
- ctx.stroke(); |
- ctx.restore(); |
- ctx.save(); |
- ctx.beginPath(); |
- ctx.font = config.legendFontStyle + " " + config.legendFontSize + "px " + config.legendFontFamily; |
- ctx.fillStyle = config.legendFontColor; |
- ctx.textAlign = "left"; |
- ctx.textBaseline = "bottom"; |
- ctx.translate(xpos + config.legendBlockSize + config.legendSpaceBetweenBoxAndText, ypos); |
- ctx.fillText(lgtxt, 0, 0); |
- ctx.stroke(); |
- ctx.restore(); |
- } |
- } |
- } |
-}; |