Skip to content

Commit

Permalink
Add reverse support to category scale
Browse files Browse the repository at this point in the history
  • Loading branch information
nagix committed Jun 15, 2019
1 parent 70b32ff commit 0e30b9b
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 48 deletions.
24 changes: 21 additions & 3 deletions src/core/core.scale.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ defaults._set('scale', {

function getPixelForGridLine(scale, index, offsetGridLines) {
var lineValue = scale.getPixelForTick(index);
var range;

if (offsetGridLines) {
if (scale.getTicks().length === 1) {
lineValue -= scale.isHorizontal() ?
Math.max(lineValue - scale.left, scale.right - lineValue) :
Math.max(lineValue - scale.top, scale.bottom - lineValue);
range = scale._getRange();
lineValue -= Math.max(lineValue - range.start, range.end - lineValue);
} else if (index === 0) {
lineValue -= (scale.getPixelForTick(1) - lineValue) / 2;
} else {
Expand Down Expand Up @@ -649,6 +649,24 @@ var Scale = Element.extend({
return +this.getRightValue(rawValue);
},

/**
* @private
*/
_getRange: function() {
var me = this;
if (me.isHorizontal()) {
return {
start: me.left,
end: me.right,
size: me.right - me.left
};
}
return {
start: me.top,
end: me.bottom,
size: me.bottom - me.top
};
},
/**
* Used to get the value to display in the tooltip for the data at the given index
* @param index
Expand Down
76 changes: 39 additions & 37 deletions src/scales/scale.category.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,86 +33,88 @@ module.exports = Scale.extend({
buildTicks: function() {
var me = this;
var labels = me._getLabels();
var minIndex = me.minIndex;
var maxIndex = me.maxIndex;

// If we are viewing some subset of labels, slice the original array
me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1);
var ticks = me.ticks = (minIndex === 0 && maxIndex === labels.length - 1) ? labels : labels.slice(minIndex, maxIndex + 1);

if (me.options.ticks.reverse) {
me.ticks = ticks.slice().reverse();
}
},

convertTicksToLabels: function() {
var me = this;

me._tickValues = me.ticks.slice();
Scale.prototype.convertTicksToLabels.call(me);
},

getLabelForIndex: function(index, datasetIndex) {
var me = this;
var chart = me.chart;
var labels = me._getLabels();

if (chart.getDatasetMeta(datasetIndex).controller._getValueScaleId() === me.id) {
return me.getRightValue(chart.data.datasets[datasetIndex].data[index]);
}

return me.ticks[index - me.minIndex];
return labels[index];
},

// Used to get data value locations. Value can either be an index or a numerical value
getPixelForValue: function(value, index) {
var me = this;
var offset = me.options.offset;
// 1 is added because we need the length but we have the indexes
var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - (offset ? 0 : 1)), 1);
var options = me.options;
var offset = options.offset;
var offsetAmt = Math.max(me._ticks.length - (offset ? 0 : 1), 1);
var range = me._getRange();
var valueDimension = range.size / offsetAmt;
var valueCategory, labels, idx, pixel;

// If value is a data object, then index is the index in the data array,
// not the index of the scale. We need to change that.
var valueCategory;
if (value !== undefined && value !== null) {
valueCategory = me.isHorizontal() ? value.x : value.y;
}
if (valueCategory !== undefined || (value !== undefined && isNaN(index))) {
var labels = me._getLabels();
labels = me._getLabels();
value = valueCategory || value;
var idx = labels.indexOf(value);
idx = labels.indexOf(value);
index = idx !== -1 ? idx : index;
}

if (me.isHorizontal()) {
var valueWidth = me.width / offsetAmt;
var widthOffset = (valueWidth * (index - me.minIndex));

if (offset) {
widthOffset += (valueWidth / 2);
}

return me.left + widthOffset;
}
var valueHeight = me.height / offsetAmt;
var heightOffset = (valueHeight * (index - me.minIndex));
pixel = valueDimension * (index - me.minIndex);

if (offset) {
heightOffset += (valueHeight / 2);
pixel += valueDimension / 2;
}

return me.top + heightOffset;
return options.ticks.reverse ? range.end - pixel : range.start + pixel;
},

getPixelForTick: function(index) {
return this.getPixelForValue(this.ticks[index], index + this.minIndex, null);
var me = this;

return me.getPixelForValue(me._tickValues[index]);
},

getValueForPixel: function(pixel) {
var me = this;
var offset = me.options.offset;
var value;
var offsetAmt = Math.max((me._ticks.length - (offset ? 0 : 1)), 1);
var horz = me.isHorizontal();
var valueDimension = (horz ? me.width : me.height) / offsetAmt;
var options = me.options;
var offset = options.offset;
var offsetAmt = Math.max(me._ticks.length - (offset ? 0 : 1), 1);
var range = me._getRange();
var valueDimension = range.size / offsetAmt;

pixel -= horz ? me.left : me.top;
pixel = options.ticks.reverse ? range.end - pixel : pixel - range.start;

if (offset) {
pixel -= (valueDimension / 2);
}

if (pixel <= 0) {
value = 0;
} else {
value = Math.round(pixel / valueDimension);
pixel -= valueDimension / 2;
}

return value + me.minIndex;
return Math.round(pixel / valueDimension) + me.minIndex;
},

getBasePixel: function() {
Expand Down
15 changes: 7 additions & 8 deletions src/scales/scale.time.js
Original file line number Diff line number Diff line change
Expand Up @@ -704,13 +704,12 @@ module.exports = Scale.extend({
*/
getPixelForOffset: function(time) {
var me = this;
var isReverse = me.options.ticks.reverse;
var size = me._horizontal ? me.width : me.height;
var start = me._horizontal ? isReverse ? me.right : me.left : isReverse ? me.bottom : me.top;
var offsets = me._offsets;
var range = me._getRange();
var pos = interpolate(me._table, 'time', time, 'pos');
var offset = size * (me._offsets.start + pos) / (me._offsets.start + 1 + me._offsets.end);
var offset = range.size * (offsets.start + pos) / (offsets.start + 1 + offsets.end);

return isReverse ? start - offset : start + offset;
return me.options.ticks.reverse ? range.end - offset : range.start + offset;
},

getPixelForValue: function(value, index, datasetIndex) {
Expand Down Expand Up @@ -739,9 +738,9 @@ module.exports = Scale.extend({

getValueForPixel: function(pixel) {
var me = this;
var size = me._horizontal ? me.width : me.height;
var start = me._horizontal ? me.left : me.top;
var pos = (size ? (pixel - start) / size : 0) * (me._offsets.start + 1 + me._offsets.start) - me._offsets.end;
var offsets = me._offsets;
var range = me._getRange();
var pos = (range.size ? (pixel - range.start) / range.size : 0) * (offsets.start + 1 + offsets.end) - offsets.start;
var time = interpolate(me._table, 'pos', pos, 'time');

// DEPRECATION, we should return time directly
Expand Down
87 changes: 87 additions & 0 deletions test/specs/scale.category.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,4 +390,91 @@ describe('Category scale tests', function() {
expect(yScale.getPixelForValue(0, 1, 0)).toBeCloseToPixel(107);
expect(yScale.getPixelForValue(0, 3, 0)).toBeCloseToPixel(407);
});

describe('when ticks.reverse is true', function() {
beforeEach(function() {
this.chart = window.acquireChart({
type: 'line',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: [10, 5, 0, 25, 78]
}],
labels: ['tick1', 'tick2', 'tick3', 'tick4', 'tick5']
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'category',
ticks: {
reverse: true
}
}],
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});
});

it('should get the correct label for the index', function() {
var scale = this.chart.scales.xScale0;

expect(scale.getLabelForIndex(1, 0)).toBe('tick2');
});

it('should generate the correct tick labels', function() {
var scale = this.chart.scales.xScale0;

expect(scale.ticks).toEqual(['tick5', 'tick4', 'tick3', 'tick2', 'tick1']);
});

it('Should get the correct pixel for a value', function() {
var chart = this.chart;
var scale = chart.scales.xScale0;

expect(scale.getPixelForValue(null, 4, 0)).toBeCloseToPixel(29);
expect(scale.getPixelForValue('tick5')).toBeCloseToPixel(29);

expect(scale.getPixelForValue(null, 0, 0)).toBeCloseToPixel(496);
expect(scale.getPixelForValue('tick1')).toBeCloseToPixel(496);

scale.options.offset = true;
chart.update();

expect(scale.getPixelForValue(null, 4, 0)).toBeCloseToPixel(77);
expect(scale.getPixelForValue('tick5')).toBeCloseToPixel(77);

expect(scale.getPixelForValue(null, 0, 0)).toBeCloseToPixel(461);
expect(scale.getPixelForValue('tick1')).toBeCloseToPixel(461);
});

it('Should get the correct pixel for a value when zoomed', function() {
var chart = this.chart;
var scale = chart.scales.xScale0;

scale.options.ticks.min = 'tick2';
scale.options.ticks.max = 'tick4';
chart.update();

expect(scale.getPixelForValue(null, 3, 0)).toBeCloseToPixel(29);
expect(scale.getPixelForValue('tick4')).toBeCloseToPixel(29);

expect(scale.getPixelForValue(null, 1, 0)).toBeCloseToPixel(496);
expect(scale.getPixelForValue('tick2')).toBeCloseToPixel(496);

scale.options.offset = true;
chart.update();

expect(scale.getPixelForValue(null, 3, 0)).toBeCloseToPixel(109);
expect(scale.getPixelForValue('tick4')).toBeCloseToPixel(109);

expect(scale.getPixelForValue(null, 1, 0)).toBeCloseToPixel(429);
expect(scale.getPixelForValue('tick2')).toBeCloseToPixel(429);
});
});
});

0 comments on commit 0e30b9b

Please sign in to comment.