Skip to content

Commit

Permalink
Improve offset calculation for scale.offset option
Browse files Browse the repository at this point in the history
- Offset is calulated based on the intervals between the first two data points and the last two data points (barThickness: 'flex') or the minimum interval of all data (barThickness: undefined).
- Add test for both cases of barThickness: 'flex' and undefined.
  • Loading branch information
nagix committed Jun 29, 2018
1 parent 88308c6 commit a2ec063
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/controllers/controller.bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ function computeFlexCategoryTraits(index, ruler, options) {
if (prev === null) {
// first data: its size is double based on the next point or,
// if it's also the last data, we use the scale end extremity.
prev = curr - (next === null ? ruler.end - curr : next - curr);
prev = curr - (next === null ? Math.max(curr - ruler.start, ruler.end - curr) * 2 : next - curr);
}

if (next === null) {
Expand Down
66 changes: 47 additions & 19 deletions src/scales/scale.time.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,27 +361,55 @@ function generate(min, max, capacity, options) {
* Returns the right and left offsets from edges in the form of {left, right}.
* Offsets are added when the `offset` option is true.
*/
function computeOffsets(table, ticks, min, max, options) {
function computeOffsets(table, ticks, data, min, max, options) {
var minInterval = 1;
var left = 0;
var right = 0;
var upper, lower;

if (options.offset && ticks.length) {
if (!options.time.min) {
upper = ticks.length > 1 ? ticks[1] : max;
lower = ticks[0];
left = (
interpolate(table, 'time', upper, 'pos') -
interpolate(table, 'time', lower, 'pos')
) / 2;
var timestamps = [];
var timeOpts = options.time;
var i, ilen, curr, prev, length, first, last, width;

if (options.offset) {
data.forEach(function(timestamp) {
if (timestamp >= min && timestamp <= max) {
timestamps.push(timestamp);
}
});

if (!options.barThickness) {
[data, ticks].forEach(function(arr) {
for (i = 0, ilen = arr.length; i < ilen; ++i) {
curr = interpolate(table, 'time', arr[i], 'pos');
minInterval = i > 0 ? Math.min(minInterval, curr - prev) : minInterval;
prev = curr;
}
});
}
if (!options.time.max) {
upper = ticks[ticks.length - 1];
lower = ticks.length > 1 ? ticks[ticks.length - 2] : min;
right = (
interpolate(table, 'time', upper, 'pos') -
interpolate(table, 'time', lower, 'pos')
) / 2;

length = timestamps.length;
if (length) {
if (!timeOpts.min) {
first = interpolate(table, 'time', timestamps[0], 'pos');
if (length === 1) {
width = (1 - first) * 2;
} else if (options.barThickness) {
width = interpolate(table, 'time', timestamps[1], 'pos') - first;
} else {
width = minInterval;
}
left = Math.max(width / 2 - first, 0);
}
if (!timeOpts.max) {
last = interpolate(table, 'time', timestamps[length - 1], 'pos');
if (length === 1) {
width = last * 2;
} else if (options.barThickness) {
width = last - interpolate(table, 'time', timestamps[length - 2], 'pos');
} else {
width = minInterval;
}
right = Math.max(width / 2 - (1 - last), 0);
}
}
}

Expand Down Expand Up @@ -643,7 +671,7 @@ module.exports = function() {
me._unit = timeOpts.unit || determineUnitForFormatting(ticks, timeOpts.minUnit, me.min, me.max);
me._majorUnit = determineMajorUnit(me._unit);
me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution);
me._offsets = computeOffsets(me._table, ticks, min, max, options);
me._offsets = computeOffsets(me._table, ticks, me._timestamps.data, min, max, options);
me._labelFormat = determineLabelFormat(me._timestamps.data, timeOpts);

return ticksFromTimestamps(ticks, me._majorUnit);
Expand Down
Binary file modified test/fixtures/controller.bar/bar-thickness-offset.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 24 additions & 5 deletions test/specs/scale.time.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1276,16 +1276,35 @@ describe('Time scale tests', function() {
var chart = this.chart;
var scale = chart.scales.x;
var options = chart.options.scales.xAxes[0];
var minInterval;

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

var numTicks = scale.ticks.length;
var firstTickInterval = scale.getPixelForTick(1) - scale.getPixelForTick(0);
var lastTickInterval = scale.getPixelForTick(numTicks - 1) - scale.getPixelForTick(numTicks - 2);
if (source === 'auto' && distribution === 'series') {
minInterval = scale.getPixelForTick(5) - scale.getPixelForTick(4);
} else {
minInterval = scale.getPixelForValue('2020') - scale.getPixelForValue('2019');
}

expect(scale.getPixelForValue('2017')).toBeCloseToPixel(scale.left + minInterval / 2);
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(scale.left + scale.width - minInterval / 2);
});

it ('should add offset from the edges if offset is true and barThickness is "flex"', function() {
var chart = this.chart;
var scale = chart.scales.x;
var options = chart.options.scales.xAxes[0];

options.offset = true;
options.barThickness = 'flex';
chart.update();

var firstInterval = scale.getPixelForValue('2019') - scale.getPixelForValue('2017');
var lastInterval = scale.getPixelForValue('2042') - scale.getPixelForValue('2025');

expect(scale.getPixelForValue('2017')).toBeCloseToPixel(scale.left + firstTickInterval / 2);
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(scale.left + scale.width - lastTickInterval / 2);
expect(scale.getPixelForValue('2017')).toBeCloseToPixel(scale.left + firstInterval / 2);
expect(scale.getPixelForValue('2042')).toBeCloseToPixel(scale.left + scale.width - lastInterval / 2);
});

it ('should not add offset if min and max extend the labels range', function() {
Expand Down

0 comments on commit a2ec063

Please sign in to comment.