scale.linear.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. 'use strict';
  2. module.exports = function(Chart) {
  3. var helpers = Chart.helpers;
  4. var defaultConfig = {
  5. position: 'left',
  6. ticks: {
  7. callback: Chart.Ticks.formatters.linear
  8. }
  9. };
  10. var LinearScale = Chart.LinearScaleBase.extend({
  11. determineDataLimits: function() {
  12. var me = this;
  13. var opts = me.options;
  14. var chart = me.chart;
  15. var data = chart.data;
  16. var datasets = data.datasets;
  17. var isHorizontal = me.isHorizontal();
  18. function IDMatches(meta) {
  19. return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
  20. }
  21. // First Calculate the range
  22. me.min = null;
  23. me.max = null;
  24. if (opts.stacked) {
  25. var valuesPerType = {};
  26. helpers.each(datasets, function(dataset, datasetIndex) {
  27. var meta = chart.getDatasetMeta(datasetIndex);
  28. if (valuesPerType[meta.type] === undefined) {
  29. valuesPerType[meta.type] = {
  30. positiveValues: [],
  31. negativeValues: []
  32. };
  33. }
  34. // Store these per type
  35. var positiveValues = valuesPerType[meta.type].positiveValues;
  36. var negativeValues = valuesPerType[meta.type].negativeValues;
  37. if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
  38. helpers.each(dataset.data, function(rawValue, index) {
  39. var value = +me.getRightValue(rawValue);
  40. if (isNaN(value) || meta.data[index].hidden) {
  41. return;
  42. }
  43. positiveValues[index] = positiveValues[index] || 0;
  44. negativeValues[index] = negativeValues[index] || 0;
  45. if (opts.relativePoints) {
  46. positiveValues[index] = 100;
  47. } else if (value < 0) {
  48. negativeValues[index] += value;
  49. } else {
  50. positiveValues[index] += value;
  51. }
  52. });
  53. }
  54. });
  55. helpers.each(valuesPerType, function(valuesForType) {
  56. var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
  57. var minVal = helpers.min(values);
  58. var maxVal = helpers.max(values);
  59. me.min = me.min === null ? minVal : Math.min(me.min, minVal);
  60. me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
  61. });
  62. } else {
  63. helpers.each(datasets, function(dataset, datasetIndex) {
  64. var meta = chart.getDatasetMeta(datasetIndex);
  65. if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
  66. helpers.each(dataset.data, function(rawValue, index) {
  67. var value = +me.getRightValue(rawValue);
  68. if (isNaN(value) || meta.data[index].hidden) {
  69. return;
  70. }
  71. if (me.min === null) {
  72. me.min = value;
  73. } else if (value < me.min) {
  74. me.min = value;
  75. }
  76. if (me.max === null) {
  77. me.max = value;
  78. } else if (value > me.max) {
  79. me.max = value;
  80. }
  81. });
  82. }
  83. });
  84. }
  85. // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
  86. this.handleTickRangeOptions();
  87. },
  88. getTickLimit: function() {
  89. var maxTicks;
  90. var me = this;
  91. var tickOpts = me.options.ticks;
  92. if (me.isHorizontal()) {
  93. maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50));
  94. } else {
  95. // The factor of 2 used to scale the font size has been experimentally determined.
  96. var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize);
  97. maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize)));
  98. }
  99. return maxTicks;
  100. },
  101. // Called after the ticks are built. We need
  102. handleDirectionalChanges: function() {
  103. if (!this.isHorizontal()) {
  104. // We are in a vertical orientation. The top value is the highest. So reverse the array
  105. this.ticks.reverse();
  106. }
  107. },
  108. getLabelForIndex: function(index, datasetIndex) {
  109. return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
  110. },
  111. // Utils
  112. getPixelForValue: function(value) {
  113. // This must be called after fit has been run so that
  114. // this.left, this.top, this.right, and this.bottom have been defined
  115. var me = this;
  116. var start = me.start;
  117. var rightValue = +me.getRightValue(value);
  118. var pixel;
  119. var range = me.end - start;
  120. if (me.isHorizontal()) {
  121. pixel = me.left + (me.width / range * (rightValue - start));
  122. return Math.round(pixel);
  123. }
  124. pixel = me.bottom - (me.height / range * (rightValue - start));
  125. return Math.round(pixel);
  126. },
  127. getValueForPixel: function(pixel) {
  128. var me = this;
  129. var isHorizontal = me.isHorizontal();
  130. var innerDimension = isHorizontal ? me.width : me.height;
  131. var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension;
  132. return me.start + ((me.end - me.start) * offset);
  133. },
  134. getPixelForTick: function(index) {
  135. return this.getPixelForValue(this.ticksAsNumbers[index]);
  136. }
  137. });
  138. Chart.scaleService.registerScaleType('linear', LinearScale, defaultConfig);
  139. };