Skip to content

Commit e33e1ff

Browse files
committed
Simplify the tick generation code
1 parent 48aecb4 commit e33e1ff

File tree

5 files changed

+66
-48
lines changed

5 files changed

+66
-48
lines changed

src/scales/scale.linear.js

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict';
22

3-
var defaults = require('../core/core.defaults');
43
var helpers = require('../helpers/index');
54
var scaleService = require('../core/core.scaleService');
65
var Ticks = require('../core/core.ticks');
@@ -134,16 +133,22 @@ module.exports = function(Chart) {
134133
this.handleTickRangeOptions();
135134
},
136135
getTickLimit: function() {
137-
var maxTicks;
138136
var me = this;
139137
var tickOpts = me.options.ticks;
140-
141-
if (me.isHorizontal()) {
142-
maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 40));
138+
var stepSize = tickOpts.stepSize;
139+
var maxTicksLimit = tickOpts.maxTicksLimit;
140+
var maxTicks, tickFont;
141+
142+
if (stepSize > 0) {
143+
maxTicks = Math.ceil(me.max / stepSize) - Math.floor(me.min / stepSize) + 1;
144+
} else if (me.isHorizontal()) {
145+
maxTicks = Math.ceil(me.width / 40);
143146
} else {
144-
// The factor of 2 used to scale the font size has been experimentally determined.
145-
var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, defaults.global.defaultFontSize);
146-
maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (1.5 * tickFontSize)));
147+
tickFont = helpers.options._parseFont(tickOpts);
148+
maxTicks = Math.ceil(me.height / tickFont.lineHeight);
149+
}
150+
if (maxTicksLimit || !(stepSize > 0)) {
151+
maxTicks = Math.min(maxTicksLimit || 11, maxTicks);
147152
}
148153

149154
return maxTicks;

src/scales/scale.linearbase.js

+24-36
Original file line numberDiff line numberDiff line change
@@ -16,52 +16,41 @@ function generateTicks(generationOptions, dataRange) {
1616
// for details.
1717

1818
var stepSize = generationOptions.stepSize;
19+
var unit = stepSize > 0 ? stepSize : 1;
20+
var maxNumSpaces = generationOptions.maxTicks - 1;
1921
var min = generationOptions.min;
2022
var max = generationOptions.max;
21-
var spacing, precision, factor, niceMin, niceMax, numSpaces, maxNumSpaces;
22-
23-
if (stepSize && stepSize > 0) {
24-
spacing = stepSize;
25-
if (generationOptions.maxTicksLimit) {
26-
maxNumSpaces = generationOptions.maxTicksLimit - 1;
27-
// spacing is set to stepSize multiplied by a nice number of
28-
// Math.ceil((max - min) / maxNumSpaces / stepSize) = num of steps that should be grouped
29-
spacing *= helpers.niceNum(Math.ceil((dataRange.max - dataRange.min) / maxNumSpaces / stepSize));
30-
numSpaces = Math.ceil(dataRange.max / spacing) - Math.floor(dataRange.min / spacing);
31-
if (numSpaces > maxNumSpaces) {
32-
// If the calculated num of spaces exceeds maxNumSpaces, recalculate it
33-
spacing = helpers.niceNum(Math.ceil(numSpaces * spacing / maxNumSpaces / stepSize)) * stepSize;
34-
}
35-
}
36-
} else {
37-
maxNumSpaces = generationOptions.maxTicks - 1;
38-
// spacing is set to a nice number of (max - min) / maxNumSpaces
39-
spacing = helpers.niceNum((dataRange.max - dataRange.min) / maxNumSpaces);
40-
numSpaces = Math.ceil(dataRange.max / spacing) - Math.floor(dataRange.min / spacing);
41-
if (numSpaces > maxNumSpaces) {
42-
// If the calculated num of spaces exceeds maxNumSpaces, recalculate it
43-
spacing = helpers.niceNum(numSpaces * spacing / maxNumSpaces);
44-
}
45-
46-
precision = generationOptions.precision;
47-
if (!helpers.isNullOrUndef(precision)) {
48-
// If the user specified a precision, round to that number of decimal places
49-
factor = Math.pow(10, precision);
50-
spacing = Math.ceil(spacing * factor) / factor;
51-
}
23+
var precision = generationOptions.precision;
24+
var spacing, factor, niceMin, niceMax, numSpaces;
25+
26+
// spacing is set to a nice number of the dataRange divided by maxNumSpaces.
27+
// stepSize is used as a minimum unit if it is specified.
28+
spacing = helpers.niceNum((dataRange.max - dataRange.min) / maxNumSpaces / unit) * unit;
29+
numSpaces = Math.ceil(dataRange.max / spacing) - Math.floor(dataRange.min / spacing);
30+
if (numSpaces > maxNumSpaces) {
31+
// If the calculated num of spaces exceeds maxNumSpaces, recalculate it
32+
spacing = helpers.niceNum(numSpaces * spacing / maxNumSpaces / unit) * unit;
5233
}
53-
// If a precision is not specified, calculate factor based on spacing
54-
if (!factor) {
34+
35+
if (!(stepSize > 0) && !helpers.isNullOrUndef(precision)) {
36+
// If the user specified a precision, round to that number of decimal places
37+
factor = Math.pow(10, precision);
38+
spacing = Math.ceil(spacing * factor) / factor;
39+
} else {
40+
// If a precision is not specified, calculate factor based on spacing
5541
factor = Math.pow(10, helpers.decimalPlaces(spacing));
5642
}
43+
5744
niceMin = Math.floor(dataRange.min / spacing) * spacing;
5845
niceMax = Math.ceil(dataRange.max / spacing) * spacing;
5946

6047
// If min, max and stepSize is set and they make an evenly spaced scale use it.
61-
if (!helpers.isNullOrUndef(min) && !helpers.isNullOrUndef(max) && stepSize) {
48+
if (stepSize > 0) {
6249
// If very close to our whole number, use it.
63-
if (helpers.almostWhole((max - min) / stepSize, spacing / 1000)) {
50+
if (!helpers.isNullOrUndef(min) && helpers.almostWhole(min / spacing, spacing / 1000)) {
6451
niceMin = min;
52+
}
53+
if (!helpers.isNullOrUndef(max) && helpers.almostWhole(max / spacing, spacing / 1000)) {
6554
niceMax = max;
6655
}
6756
}
@@ -180,7 +169,6 @@ module.exports = function(Chart) {
180169

181170
var numericGeneratorOptions = {
182171
maxTicks: maxTicks,
183-
maxTicksLimit: tickOpts.maxTicksLimit,
184172
min: tickOpts.min,
185173
max: tickOpts.max,
186174
precision: tickOpts.precision,

src/scales/scale.radialLinear.js

+16-3
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,23 @@ module.exports = function(Chart) {
358358
me.handleTickRangeOptions();
359359
},
360360
getTickLimit: function() {
361-
var opts = this.options;
361+
var me = this;
362+
var opts = me.options;
362363
var tickOpts = opts.ticks;
363-
var tickBackdropHeight = getTickBackdropHeight(opts);
364-
return Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(this.drawingArea / tickBackdropHeight));
364+
var stepSize = tickOpts.stepSize;
365+
var maxTicksLimit = tickOpts.maxTicksLimit;
366+
var maxTicks;
367+
368+
if (stepSize > 0) {
369+
maxTicks = Math.ceil(me.max / stepSize) - Math.floor(me.min / stepSize) + 1;
370+
} else {
371+
maxTicks = Math.ceil(me.drawingArea / getTickBackdropHeight(opts));
372+
}
373+
if (maxTicksLimit || !(stepSize > 0)) {
374+
maxTicks = Math.min(maxTicksLimit || 11, maxTicks);
375+
}
376+
377+
return maxTicks;
365378
},
366379
convertTicksToLabels: function() {
367380
var me = this;

test/specs/scale.linear.tests.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ describe('Linear Scale', function() {
570570
expect(chart.scales.yScale0).not.toEqual(undefined); // must construct
571571
expect(chart.scales.yScale0.min).toBe(1);
572572
expect(chart.scales.yScale0.max).toBe(11);
573-
expect(chart.scales.yScale0.ticks).toEqual(['11', '9', '7', '5', '3', '1']);
573+
expect(chart.scales.yScale0.ticks).toEqual(['11', '10', '8', '6', '4', '2', '1']);
574574
});
575575

576576
it('Should create decimal steps if stepSize is a decimal number', function() {
@@ -788,6 +788,12 @@ describe('Linear Scale', function() {
788788
chart.update();
789789

790790
expect(chart.scales.yScale.ticks).toEqual(['2.5', '2.0', '1.5', '1.0', '0.5']);
791+
792+
chart.options.scales.yAxes[0].ticks.min = 0.3;
793+
chart.options.scales.yAxes[0].ticks.max = 2.8;
794+
chart.update();
795+
796+
expect(chart.scales.yScale.ticks).toEqual(['2.8', '2.5', '2.0', '1.5', '1.0', '0.5', '0.3']);
791797
});
792798

793799
it('Should build labels using the user supplied callback', function() {

test/specs/scale.radialLinear.tests.js

+6
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@ describe('Test the radial linear scale', function() {
311311
chart.update();
312312

313313
expect(chart.scale.ticks).toEqual(['0.5', '1.0', '1.5', '2.0', '2.5']);
314+
315+
chart.options.scale.ticks.min = 0.3;
316+
chart.options.scale.ticks.max = 2.8;
317+
chart.update();
318+
319+
expect(chart.scale.ticks).toEqual(['0.3', '0.5', '1.0', '1.5', '2.0', '2.5', '2.8']);
314320
});
315321

316322
it('Should build labels using the user supplied callback', function() {

0 commit comments

Comments
 (0)