From 9a20381af46a78576f53b48e0b6e789f55877a06 Mon Sep 17 00:00:00 2001 From: Robert Becker Date: Thu, 4 Feb 2016 15:20:17 +0100 Subject: [PATCH] Fixed typo in core.helpers.js. Added ticks.fixedStepSize configuration parameter to force linear scale steps. --- src/core/core.helpers.js | 2 +- src/scales/scale.linear.js | 386 +++++++++++++++++++------------------ 2 files changed, 197 insertions(+), 191 deletions(-) diff --git a/src/core/core.helpers.js b/src/core/core.helpers.js index 470bc0d9c..781b4875e 100644 --- a/src/core/core.helpers.js +++ b/src/core/core.helpers.js @@ -843,7 +843,7 @@ }, isDatasetVisible = helpers.isDatasetVisible = function(dataset) { return !dataset.hidden; - }; + }, pushAllIfDefined = helpers.pushAllIfDefined = function(element, array) { if (typeof element == "undefined") { return; diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js index 2cc8254e6..774e61ce8 100644 --- a/src/scales/scale.linear.js +++ b/src/scales/scale.linear.js @@ -1,233 +1,239 @@ -(function() { - "use strict"; +(function () { + "use strict"; - var root = this, - Chart = root.Chart, - helpers = Chart.helpers; + var root = this, + Chart = root.Chart, + helpers = Chart.helpers; - var defaultConfig = { - position: "left", - ticks: { - callback: function(tickValue, index, ticks) { - var delta = ticks[1] - ticks[0]; + var defaultConfig = { + position: "left", + ticks: { + callback: function (tickValue, index, ticks) { + var delta = ticks[1] - ticks[0]; - // If we have a number like 2.5 as the delta, figure out how many decimal places we need - if (Math.abs(delta) > 1) { - if (tickValue !== Math.floor(tickValue)) { - // not an integer - delta = tickValue - Math.floor(tickValue); - } - } + // If we have a number like 2.5 as the delta, figure out how many decimal places we need + if (Math.abs(delta) > 1) { + if (tickValue !== Math.floor(tickValue)) { + // not an integer + delta = tickValue - Math.floor(tickValue); + } + } - var logDelta = helpers.log10(Math.abs(delta)); - var tickString = ''; + var logDelta = helpers.log10(Math.abs(delta)); + var tickString = ''; - if (tickValue !== 0) { - var numDecimal = -1 * Math.floor(logDelta); - numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places - tickString = tickValue.toFixed(numDecimal); - } else { - tickString = '0'; // never show decimal places for 0 - } + if (tickValue !== 0) { + var numDecimal = -1 * Math.floor(logDelta); + numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places + tickString = tickValue.toFixed(numDecimal); + } else { + tickString = '0'; // never show decimal places for 0 + } - return tickString; - } - } - }; + return tickString; + } + } + }; - var LinearScale = Chart.Scale.extend({ - buildTicks: function() { + var LinearScale = Chart.Scale.extend({ + buildTicks: function () { - // First Calculate the range - this.min = null; - this.max = null; + // First Calculate the range + this.min = null; + this.max = null; - if (this.options.stacked) { - var valuesPerType = {}; + if (this.options.stacked) { + var valuesPerType = {}; - helpers.each(this.chart.data.datasets, function(dataset) { - if (valuesPerType[dataset.type] === undefined) { - valuesPerType[dataset.type] = { - positiveValues: [], - negativeValues: [], - }; - } + helpers.each(this.chart.data.datasets, function (dataset) { + if (valuesPerType[dataset.type] === undefined) { + valuesPerType[dataset.type] = { + positiveValues: [], + negativeValues: [], + }; + } - // Store these per type - var positiveValues = valuesPerType[dataset.type].positiveValues; - var negativeValues = valuesPerType[dataset.type].negativeValues; + // Store these per type + var positiveValues = valuesPerType[dataset.type].positiveValues; + var negativeValues = valuesPerType[dataset.type].negativeValues; - if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) { - helpers.each(dataset.data, function(rawValue, index) { + if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) { + helpers.each(dataset.data, function (rawValue, index) { - var value = +this.getRightValue(rawValue); - if (isNaN(value)) { - return; - } + var value = +this.getRightValue(rawValue); + if (isNaN(value)) { + return; + } - positiveValues[index] = positiveValues[index] || 0; - negativeValues[index] = negativeValues[index] || 0; + positiveValues[index] = positiveValues[index] || 0; + negativeValues[index] = negativeValues[index] || 0; - if (this.options.relativePoints) { - positiveValues[index] = 100; - } else { - if (value < 0) { - negativeValues[index] += value; - } else { - positiveValues[index] += value; - } - } - }, this); - } - }, this); + if (this.options.relativePoints) { + positiveValues[index] = 100; + } else { + if (value < 0) { + negativeValues[index] += value; + } else { + positiveValues[index] += value; + } + } + }, this); + } + }, this); - helpers.each(valuesPerType, function(valuesForType) { - var values = valuesForType.positiveValues.concat(valuesForType.negativeValues); - var minVal = helpers.min(values); - var maxVal = helpers.max(values); - this.min = this.min === null ? minVal : Math.min(this.min, minVal); - this.max = this.max === null ? maxVal : Math.max(this.max, maxVal); - }, this); + helpers.each(valuesPerType, function (valuesForType) { + var values = valuesForType.positiveValues.concat(valuesForType.negativeValues); + var minVal = helpers.min(values); + var maxVal = helpers.max(values); + this.min = this.min === null ? minVal : Math.min(this.min, minVal); + this.max = this.max === null ? maxVal : Math.max(this.max, maxVal); + }, this); - } else { - helpers.each(this.chart.data.datasets, function(dataset) { - if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) { - helpers.each(dataset.data, function(rawValue, index) { - var value = +this.getRightValue(rawValue); - if (isNaN(value)) { - return; - } + } else { + helpers.each(this.chart.data.datasets, function (dataset) { + if (helpers.isDatasetVisible(dataset) && (this.isHorizontal() ? dataset.xAxisID === this.id : dataset.yAxisID === this.id)) { + helpers.each(dataset.data, function (rawValue, index) { + var value = +this.getRightValue(rawValue); + if (isNaN(value)) { + return; + } - if (this.min === null) { - this.min = value; - } else if (value < this.min) { - this.min = value; - } + if (this.min === null) { + this.min = value; + } else if (value < this.min) { + this.min = value; + } - if (this.max === null) { - this.max = value; - } else if (value > this.max) { - this.max = value; - } - }, this); - } - }, this); - } + if (this.max === null) { + this.max = value; + } else if (value > this.max) { + this.max = value; + } + }, this); + } + }, this); + } - // Then calulate the ticks - this.ticks = []; + // Then calulate the ticks + this.ticks = []; - // Figure out what the max number of ticks we can support it is based on the size of - // the axis area. For now, we say that the minimum tick spacing in pixels must be 50 - // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on - // the graph + // Figure out what the max number of ticks we can support it is based on the size of + // the axis area. For now, we say that the minimum tick spacing in pixels must be 50 + // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on + // the graph - var maxTicks; + var maxTicks; - if (this.isHorizontal()) { - maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, - Math.ceil(this.width / 50)); - } else { - // The factor of 2 used to scale the font size has been experimentally determined. - maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, - Math.ceil(this.height / (2 * this.options.ticks.fontSize))); - } + if (this.isHorizontal()) { + maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, + Math.ceil(this.width / 50)); + } else { + // The factor of 2 used to scale the font size has been experimentally determined. + maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, + Math.ceil(this.height / (2 * this.options.ticks.fontSize))); + } - // Make sure we always have at least 2 ticks - maxTicks = Math.max(2, maxTicks); + // Make sure we always have at least 2 ticks + maxTicks = Math.max(2, maxTicks); - // To get a "nice" value for the tick spacing, we will use the appropriately named - // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks - // for details. + // To get a "nice" value for the tick spacing, we will use the appropriately named + // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks + // for details. - // If we are forcing it to begin at 0, but 0 will already be rendered on the chart, - // do nothing since that would make the chart weird. If the user really wants a weird chart - // axis, they can manually override it - if (this.options.ticks.beginAtZero) { - var minSign = helpers.sign(this.min); - var maxSign = helpers.sign(this.max); + // If we are forcing it to begin at 0, but 0 will already be rendered on the chart, + // do nothing since that would make the chart weird. If the user really wants a weird chart + // axis, they can manually override it + if (this.options.ticks.beginAtZero) { + var minSign = helpers.sign(this.min); + var maxSign = helpers.sign(this.max); - if (minSign < 0 && maxSign < 0) { - // move the top up to 0 - this.max = 0; - } else if (minSign > 0 && maxSign > 0) { - // move the botttom down to 0 - this.min = 0; - } - } + if (minSign < 0 && maxSign < 0) { + // move the top up to 0 + this.max = 0; + } else if (minSign > 0 && maxSign > 0) { + // move the botttom down to 0 + this.min = 0; + } + } - if (this.options.ticks.suggestedMin) { - this.min = Math.min(this.min, this.options.ticks.suggestedMin); - } - if (this.options.ticks.suggestedMax) { - this.max = Math.max(this.max, this.options.ticks.suggestedMax); - } + if (this.options.ticks.suggestedMin) { + this.min = Math.min(this.min, this.options.ticks.suggestedMin); + } - if (this.min === this.max) { - this.min--; - this.max++; - } + if (this.options.ticks.suggestedMax) { + this.max = Math.max(this.max, this.options.ticks.suggestedMax); + } - var niceRange = helpers.niceNum(this.max - this.min, false); - var spacing = helpers.niceNum(niceRange / (maxTicks - 1), true); - var niceMin = Math.floor(this.min / spacing) * spacing; - var niceMax = Math.ceil(this.max / spacing) * spacing; + if (this.min === this.max) { + this.min--; + this.max++; + } - var numSpaces = Math.ceil((niceMax - niceMin) / spacing); + if (this.options.ticks.fixedStepSize) { + for (var j = this.min; j <= this.max; ++j) { + console.log(j * this.options.ticks.fixedStepSize); + this.ticks.push(j * this.options.ticks.fixedStepSize); + } + } else { + var niceRange = helpers.niceNum(this.max - this.min, false); + var spacing = helpers.niceNum(niceRange / (maxTicks - 1), true); + var niceMin = Math.floor(this.min / spacing) * spacing; + var niceMax = Math.ceil(this.max / spacing) * spacing; - // Put the values into the ticks array - for (var j = 0; j <= numSpaces; ++j) { - this.ticks.push(niceMin + (j * spacing)); - } + var numSpaces = Math.ceil((niceMax - niceMin) / spacing); - if (this.options.position == "left" || this.options.position == "right") { - // We are in a vertical orientation. The top value is the highest. So reverse the array - this.ticks.reverse(); - } + // Put the values into the ticks array + for (var j = 0; j <= numSpaces; ++j) { + this.ticks.push(niceMin + (j * spacing)); + } + } - // At this point, we need to update our max and min given the tick values since we have expanded the - // range of the scale - this.max = helpers.max(this.ticks); - this.min = helpers.min(this.ticks); + if (this.options.position == "left" || this.options.position == "right") { + // We are in a vertical orientation. The top value is the highest. So reverse the array + this.ticks.reverse(); + } - if (this.options.ticks.reverse) { - this.ticks.reverse(); + // At this point, we need to update our max and min given the tick values since we have expanded the + // range of the scale + this.max = helpers.max(this.ticks); + this.min = helpers.min(this.ticks); - this.start = this.max; - this.end = this.min; - } else { - this.start = this.min; - this.end = this.max; - } + if (this.options.ticks.reverse) { + this.ticks.reverse(); - this.zeroLineIndex = this.ticks.indexOf(0); - }, + this.start = this.max; + this.end = this.min; + } else { + this.start = this.min; + this.end = this.max; + } - getLabelForIndex: function(index, datasetIndex) { - return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); - }, + this.zeroLineIndex = this.ticks.indexOf(0); + }, + getLabelForIndex: function (index, datasetIndex) { + return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); + }, + // Utils + getPixelForValue: function (value, index, datasetIndex, includeOffset) { + // This must be called after fit has been run so that + // this.left, this.top, this.right, and this.bottom have been defined + var rightValue = +this.getRightValue(value); + var pixel; + var range = this.end - this.start; - // Utils - getPixelForValue: function(value, index, datasetIndex, includeOffset) { - // This must be called after fit has been run so that - // this.left, this.top, this.right, and this.bottom have been defined - var rightValue = +this.getRightValue(value); - var pixel; - var range = this.end - this.start; + if (this.isHorizontal()) { - if (this.isHorizontal()) { - - var innerWidth = this.width - (this.paddingLeft + this.paddingRight); - pixel = this.left + (innerWidth / range * (rightValue - this.start)); - return Math.round(pixel + this.paddingLeft); - } else { - var innerHeight = this.height - (this.paddingTop + this.paddingBottom); - pixel = (this.bottom - this.paddingBottom) - (innerHeight / range * (rightValue - this.start)); - return Math.round(pixel); - } - }, - }); - Chart.scaleService.registerScaleType("linear", LinearScale, defaultConfig); + var innerWidth = this.width - (this.paddingLeft + this.paddingRight); + pixel = this.left + (innerWidth / range * (rightValue - this.start)); + return Math.round(pixel + this.paddingLeft); + } else { + var innerHeight = this.height - (this.paddingTop + this.paddingBottom); + pixel = (this.bottom - this.paddingBottom) - (innerHeight / range * (rightValue - this.start)); + return Math.round(pixel); + } + }, + }); + Chart.scaleService.registerScaleType("linear", LinearScale, defaultConfig); }).call(this);