Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 53 additions & 42 deletions src/core/core.ticks.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,40 @@ import {log10} from '../helpers/helpers.math';
*/
const formatters = {
/**
* Formatter for value labels
* @method Chart.Ticks.formatters.values
* @param value the value to display
* @return {string|string[]} the label to display
*/
* Formatter for value labels
* @method Chart.Ticks.formatters.values
* @param value the value to display
* @return {string|string[]} the label to display
*/
values(value) {
return isArray(value) ? value : '' + value;
},

/**
* Formatter for numeric ticks
* @method Chart.Ticks.formatters.numeric
* @param tickValue {number} the value to be formatted
* @param index {number} the position of the tickValue parameter in the ticks array
* @param ticks {object[]} the list of ticks being converted
* @return {string} string representation of the tickValue parameter
*/
* Formatter for numeric ticks
* @method Chart.Ticks.formatters.numeric
* @param tickValue {number} the value to be formatted
* @param index {number} the position of the tickValue parameter in the ticks array
* @param ticks {object[]} the list of ticks being converted
* @return {string} string representation of the tickValue parameter
*/
numeric(tickValue, index, ticks) {
if (tickValue === 0) {
return '0'; // never show decimal places for 0
}

const locale = this.chart.options.locale;

// all ticks are small or there huge numbers; use scientific notation
const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
let notation;
if (maxTick < 1e-4 || maxTick > 1e+15) {
notation = 'scientific';
}
let delta = tickValue; // This is used when there are less than 2 ticks as the tick interval.

// Figure out how many digits to show
// The space between the first two ticks might be smaller than normal spacing
let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;
if (ticks.length > 1) {
// all ticks are small or there huge numbers; use scientific notation
const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
if (maxTick < 1e-4 || maxTick > 1e+15) {
notation = 'scientific';
}

// If we have a number like 2.5 as the delta, figure out how many decimal places we need
if (Math.abs(delta) > 1 && tickValue !== Math.floor(tickValue)) {
// not an integer
delta = tickValue - Math.floor(tickValue);
delta = calculateDelta(tickValue, ticks);
}

const logDelta = log10(Math.abs(delta));
Expand All @@ -56,27 +51,43 @@ const formatters = {
Object.assign(options, this.options.ticks.format);

return formatNumber(tickValue, locale, options);
},


/**
* Formatter for logarithmic ticks
* @method Chart.Ticks.formatters.logarithmic
* @param tickValue {number} the value to be formatted
* @param index {number} the position of the tickValue parameter in the ticks array
* @param ticks {object[]} the list of ticks being converted
* @return {string} string representation of the tickValue parameter
*/
logarithmic(tickValue, index, ticks) {
if (tickValue === 0) {
return '0';
}
const remain = tickValue / (Math.pow(10, Math.floor(log10(tickValue))));
if (remain === 1 || remain === 2 || remain === 5) {
return formatters.numeric.call(this, tickValue, index, ticks);
}
return '';
}

};

/**
* Formatter for logarithmic ticks
* @method Chart.Ticks.formatters.logarithmic
* @param tickValue {number} the value to be formatted
* @param index {number} the position of the tickValue parameter in the ticks array
* @param ticks {object[]} the list of ticks being converted
* @return {string} string representation of the tickValue parameter
*/
formatters.logarithmic = function(tickValue, index, ticks) {
if (tickValue === 0) {
return '0';
}
const remain = tickValue / (Math.pow(10, Math.floor(log10(tickValue))));
if (remain === 1 || remain === 2 || remain === 5) {
return formatters.numeric.call(this, tickValue, index, ticks);

function calculateDelta(tickValue, ticks) {
// Figure out how many digits to show
// The space between the first two ticks might be smaller than normal spacing
let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;

// If we have a number like 2.5 as the delta, figure out how many decimal places we need
if (Math.abs(delta) > 1 && tickValue !== Math.floor(tickValue)) {
// not an integer
delta = tickValue - Math.floor(tickValue);
}
return '';
};
return delta;
}

/**
* Namespace to hold static tick generation functions
Expand Down
9 changes: 9 additions & 0 deletions test/specs/core.ticks.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,13 @@ describe('Test tick generators', function() {
expect(xLabels).toEqual(['0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']);
expect(yLabels).toEqual(['0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']);
});

describe('formatters.numeric', function() {
it('should not fail on empty or 1 item array', function() {
const scale = {chart: {options: {locale: 'en'}}, options: {ticks: {format: {}}}};
expect(Chart.Ticks.formatters.numeric.apply(scale, [1, 0, []])).toEqual('1');
expect(Chart.Ticks.formatters.numeric.apply(scale, [1, 0, [{value: 1}]])).toEqual('1');
expect(Chart.Ticks.formatters.numeric.apply(scale, [1, 0, [{value: 1}, {value: 1.01}]])).toEqual('1.00');
});
});
});