Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reverse support to time scale #5927

Merged
merged 5 commits into from Dec 20, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/core/core.scale.js
Expand Up @@ -352,7 +352,7 @@ module.exports = Element.extend({
var cosRotation, sinRotation;

// Allow 3 pixels x2 padding either side for label readability
var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6;
var tickWidth = Math.abs(me.getPixelForTick(1) - me.getPixelForTick(0)) - 6;

// Max label rotation can be set or default to 90 - also act as a loop counter
while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) {
Expand Down
8 changes: 5 additions & 3 deletions src/scales/scale.time.js
Expand Up @@ -383,7 +383,7 @@ function computeOffsets(table, ticks, min, max, options) {
}
}

return {left: left, right: right};
return options.ticks.reverse ? {left: right, right: left} : {left: left, right: right};
simonbrunel marked this conversation as resolved.
Show resolved Hide resolved
}

function ticksFromTimestamps(values, majorUnit) {
Expand Down Expand Up @@ -706,11 +706,13 @@ module.exports = function() {
*/
getPixelForOffset: function(time) {
var me = this;
var isReverse = me.options.ticks.reverse;
var size = me._horizontal ? me.width : me.height;
var start = me._horizontal ? me.left : me.top;
var start = me._horizontal ? isReverse ? me.right : me.left : isReverse ? me.bottom : me.top;
var pos = interpolate(me._table, 'time', time, 'pos');
var offset = size * (me._offsets.left + pos) / (me._offsets.left + 1 + me._offsets.right);

return start + size * (me._offsets.left + pos) / (me._offsets.left + 1 + me._offsets.right);
return isReverse ? start - offset : start + offset;
},

getPixelForValue: function(value, index, datasetIndex) {
Expand Down
187 changes: 187 additions & 0 deletions test/specs/scale.time.tests.js
Expand Up @@ -1317,4 +1317,191 @@ describe('Time scale tests', function() {
});
});
});

describe('when ticks.reverse', function() {
describe('is "true"', function() {
it ('should reverse the labels', function() {
this.chart = window.acquireChart({
type: 'line',
data: {
labels: ['2017', '2019', '2020', '2025', '2042'],
datasets: [{data: [0, 1, 2, 3, 4, 5]}]
},
options: {
scales: {
xAxes: [{
id: 'x',
type: 'time',
time: {
parser: 'YYYY',
},
ticks: {
source: 'labels',
reverse: true
}
}],
yAxes: [{
display: false
}]
}
}
});
var scale = this.chart.scales.x;
expect(scale.getPixelForValue('2017')).toBeCloseToPixel(scale.left + scale.width);
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(scale.left);
});
});
});

describe('when ticks.reverse is "true" and distribution', function() {
describe('is "series"', function() {
beforeEach(function() {
this.chart = window.acquireChart({
type: 'line',
data: {
labels: ['2017', '2019', '2020', '2025', '2042'],
datasets: [{data: [0, 1, 2, 3, 4, 5]}]
},
options: {
scales: {
xAxes: [{
id: 'x',
type: 'time',
time: {
parser: 'YYYY'
},
distribution: 'series',
ticks: {
source: 'labels',
reverse: true
}
}],
yAxes: [{
display: false
}]
}
}
});
});

it ('should reverse the labels and space data out with the same gap, whatever their time values', function() {
var scale = this.chart.scales.x;
var start = scale.left;
var slice = scale.width / 4;

expect(scale.getPixelForValue('2017')).toBeCloseToPixel(start + slice * 4);
expect(scale.getPixelForValue('2019')).toBeCloseToPixel(start + slice * 3);
expect(scale.getPixelForValue('2020')).toBeCloseToPixel(start + slice * 2);
expect(scale.getPixelForValue('2025')).toBeCloseToPixel(start + slice);
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(start);
});

it ('should reverse the labels and should add a step before if scale.min is before the first data', function() {
var chart = this.chart;
var scale = chart.scales.x;
var options = chart.options.scales.xAxes[0];

options.time.min = '2012';
chart.update();

var start = scale.left;
var slice = scale.width / 5;

expect(scale.getPixelForValue('2017')).toBeCloseToPixel(start + slice * 4);
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(start);
});

it ('should reverse the labels and should add a step after if scale.max is after the last data', function() {
var chart = this.chart;
var scale = chart.scales.x;
var options = chart.options.scales.xAxes[0];

options.time.max = '2050';
chart.update();

var start = scale.left;
var slice = scale.width / 5;

expect(scale.getPixelForValue('2017')).toBeCloseToPixel(start + slice * 5);
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(start + slice);
});

it ('should reverse the labels and should add steps before and after if scale.min/max are outside the data range', function() {
var chart = this.chart;
var scale = chart.scales.x;
var options = chart.options.scales.xAxes[0];

options.time.min = '2012';
options.time.max = '2050';
chart.update();

var start = scale.left;
var slice = scale.width / 6;

expect(scale.getPixelForValue('2017')).toBeCloseToPixel(start + slice * 5);
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(start + slice);
});
});
describe('is "linear"', function() {
beforeEach(function() {
this.chart = window.acquireChart({
type: 'line',
data: {
labels: ['2017', '2019', '2020', '2025', '2042'],
datasets: [{data: [0, 1, 2, 3, 4, 5]}]
},
options: {
scales: {
xAxes: [{
id: 'x',
type: 'time',
time: {
parser: 'YYYY'
},
distribution: 'linear',
ticks: {
source: 'labels',
reverse: true
}
}],
yAxes: [{
display: false
}]
}
}
});
});

it ('should reverse the labels and should space data out with a gap relative to their time values', function() {
var scale = this.chart.scales.x;
var start = scale.left;
var slice = scale.width / (2042 - 2017);

expect(scale.getPixelForValue('2017')).toBeCloseToPixel(start + slice * (2042 - 2017));
expect(scale.getPixelForValue('2019')).toBeCloseToPixel(start + slice * (2042 - 2019));
expect(scale.getPixelForValue('2020')).toBeCloseToPixel(start + slice * (2042 - 2020));
expect(scale.getPixelForValue('2025')).toBeCloseToPixel(start + slice * (2042 - 2025));
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(start);
});

it ('should reverse the labels and should take in account scale min and max if outside the ticks range', function() {
var chart = this.chart;
var scale = chart.scales.x;
var options = chart.options.scales.xAxes[0];

options.time.min = '2012';
options.time.max = '2050';
chart.update();

var start = scale.left;
var slice = scale.width / (2050 - 2012);

expect(scale.getPixelForValue('2017')).toBeCloseToPixel(start + slice * (2050 - 2017));
expect(scale.getPixelForValue('2019')).toBeCloseToPixel(start + slice * (2050 - 2019));
expect(scale.getPixelForValue('2020')).toBeCloseToPixel(start + slice * (2050 - 2020));
expect(scale.getPixelForValue('2025')).toBeCloseToPixel(start + slice * (2050 - 2025));
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(start + slice * (2050 - 2042));
});
});
});
});