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

Handle reverse support in core.scale #6343

Merged
merged 2 commits into from Jul 15, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 4 additions & 7 deletions src/controllers/controller.bar.js
Expand Up @@ -32,7 +32,7 @@ defaults._set('bar', {
* @private
*/
function computeMinSampleSize(scale, pixels) {
var min = scale.isHorizontal() ? scale.width : scale.height;
var min = scale._length;
var ticks = scale.getTicks();
var prev, curr, i, ilen;

Expand All @@ -42,7 +42,7 @@ function computeMinSampleSize(scale, pixels) {

for (i = 0, ilen = ticks.length; i < ilen; ++i) {
curr = scale.getPixelForTick(i);
min = i > 0 ? Math.min(min, curr - prev) : min;
min = i > 0 ? Math.min(min, Math.abs(curr - prev)) : min;
prev = curr;
}

Expand Down Expand Up @@ -262,9 +262,6 @@ module.exports = DatasetController.extend({
var scale = me._getIndexScale();
var stackCount = me.getStackCount();
var datasetIndex = me.index;
var isHorizontal = scale.isHorizontal();
var start = isHorizontal ? scale.left : scale.top;
var end = start + (isHorizontal ? scale.width : scale.height);
var pixels = [];
var i, ilen, min;

Expand All @@ -279,8 +276,8 @@ module.exports = DatasetController.extend({
return {
min: min,
pixels: pixels,
start: start,
end: end,
start: scale._startPixel,
end: scale._endPixel,
stackCount: stackCount,
scale: scale
};
Expand Down
5 changes: 5 additions & 0 deletions src/core/core.controller.js
Expand Up @@ -546,6 +546,11 @@ helpers.extend(Chart.prototype, /** @lends Chart */ {

me._layers = [];
helpers.each(me.boxes, function(box) {
// _configure is called twice, once in core.scale.update and once here.
// Here the boxes are fully updated and at their final positions.
if (box._configure) {
box._configure();
kurkle marked this conversation as resolved.
Show resolved Hide resolved
}
me._layers.push.apply(me._layers, box._layers());
}, me);

Expand Down
13 changes: 0 additions & 13 deletions src/core/core.helpers.js
Expand Up @@ -100,19 +100,6 @@ module.exports = function() {
}
return x > 0 ? 1 : -1;
};
helpers.log10 = Math.log10 ?
function(x) {
return Math.log10(x);
} :
function(x) {
var exponent = Math.log(x) * Math.LOG10E; // Math.LOG10E = 1 / Math.LN10.
// Check for whole powers of 10,
// which due to floating point rounding error should be corrected.
var powerOf10 = Math.round(exponent);
var isPowerOf10 = x === Math.pow(10, powerOf10);

return isPowerOf10 ? powerOf10 : exponent;
};
helpers.toRadians = function(degrees) {
return degrees * (Math.PI / 180);
};
Expand Down
82 changes: 53 additions & 29 deletions src/core/core.scale.js
Expand Up @@ -70,9 +70,7 @@ function getPixelForGridLine(scale, index, offsetGridLines) {

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);
lineValue -= Math.max(lineValue - scale._startPixel, scale._endPixel - lineValue);
} else if (index === 0) {
lineValue -= (scale.getPixelForTick(1) - lineValue) / 2;
} else {
Expand Down Expand Up @@ -318,6 +316,12 @@ var Scale = Element.extend({

me._ticks = ticks;

// _configure is called twice, once here, once from core.controller.updateLayout.
// Here we haven't been positioned yet, but dimensions are correct.
// Variables set in _configure are needed for calculateTickRotation, and
// it's ok that coordinates are not correct there, only dimensions matter.
me._configure();

// Tick Rotation
me.beforeCalculateTickRotation();
me.calculateTickRotation();
Expand All @@ -332,6 +336,30 @@ var Scale = Element.extend({
return me.minSize;

},

/**
* @private
*/
_configure: function() {
benmccann marked this conversation as resolved.
Show resolved Hide resolved
var me = this;
var reversePixels = me.options.ticks.reverse;
var startPixel, endPixel;

if (me.isHorizontal()) {
startPixel = me.left;
endPixel = me.right;
} else {
startPixel = me.top;
endPixel = me.bottom;
// by default vertical scales are from bottom to top, so pixels are reversed
reversePixels = !reversePixels;
}
me._startPixel = startPixel;
me._endPixel = endPixel;
me._reversePixels = reversePixels;
me._length = endPixel - startPixel;
},

afterUpdate: function() {
helpers.callback(this.options.afterUpdate, [this]);
},
Expand Down Expand Up @@ -576,10 +604,11 @@ var Scale = Element.extend({

// Shared Methods
isHorizontal: function() {
return this.options.position === 'top' || this.options.position === 'bottom';
var pos = this.options.position;
return pos === 'top' || pos === 'bottom';
},
isFullWidth: function() {
return (this.options.fullWidth);
return this.options.fullWidth;
},

// Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not
Expand Down Expand Up @@ -693,20 +722,11 @@ var Scale = Element.extend({
var me = this;
var offset = me.options.offset;
var numTicks = me._ticks.length;
if (index < 0 || index > numTicks - 1) {
return null;
}
if (me.isHorizontal()) {
var tickWidth = me.width / Math.max((numTicks - (offset ? 0 : 1)), 1);
var pixel = (tickWidth * index);
var tickWidth = 1 / Math.max(numTicks - (offset ? 0 : 1), 1);

if (offset) {
pixel += tickWidth / 2;
}

return me.left + pixel;
}
return me.top + (index * (me.height / (numTicks - 1)));
return index < 0 || index > numTicks - 1
? null
: me.getPixelForDecimal(index * tickWidth + (offset ? tickWidth / 2 : 0));
},

/**
Expand All @@ -715,9 +735,17 @@ var Scale = Element.extend({
*/
getPixelForDecimal: function(decimal) {
var me = this;
return me.isHorizontal()
? me.left + decimal * me.width
: me.top + decimal * me.height;

if (me._reversePixels) {
decimal = 1 - decimal;
}

return me._startPixel + decimal * me._length;
},

getDecimalForPixel: function(pixel) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it'd be nice to add a jsdoc to this method

var decimal = (pixel - this._startPixel) / this._length;
return Math.min(1, Math.max(0, this._reversePixels ? 1 - decimal : decimal));
},

/**
Expand Down Expand Up @@ -745,7 +773,6 @@ var Scale = Element.extend({
*/
_autoSkip: function(ticks) {
var me = this;
var isHorizontal = me.isHorizontal();
var optionTicks = me.options.ticks;
var tickCount = ticks.length;
var skipRatio = false;
Expand All @@ -755,9 +782,7 @@ var Scale = Element.extend({
// drawn as their center at end of axis, so tickCount-1
var ticksLength = me._tickSize() * (tickCount - 1);

// Axis length
var axisLength = isHorizontal ? me.width : me.height;

var axisLength = me._length;
var result = [];
var i, tick;

Expand Down Expand Up @@ -788,7 +813,6 @@ var Scale = Element.extend({
*/
_tickSize: function() {
var me = this;
var isHorizontal = me.isHorizontal();
var optionTicks = me.options.ticks;

// Calculate space needed by label in axis direction.
Expand All @@ -802,7 +826,7 @@ var Scale = Element.extend({
var h = labelSizes ? labelSizes.highest.height + padding : 0;

// Calculate space needed for 1 tick in axis direction.
return isHorizontal
return me.isHorizontal()
? h * cos > w * sin ? w / cos : h / sin
: h * sin < w * cos ? h / cos : w / sin;
},
Expand Down Expand Up @@ -1130,7 +1154,7 @@ var Scale = Element.extend({
var scaleLabelX, scaleLabelY;

if (me.isHorizontal()) {
scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
scaleLabelX = me.left + me.width / 2; // midpoint of the width
scaleLabelY = position === 'bottom'
? me.bottom - halfLineHeight - scaleLabelPadding.bottom
: me.top + halfLineHeight + scaleLabelPadding.top;
Expand All @@ -1139,7 +1163,7 @@ var Scale = Element.extend({
scaleLabelX = isLeft
? me.left + halfLineHeight + scaleLabelPadding.top
: me.right - halfLineHeight - scaleLabelPadding.top;
scaleLabelY = me.top + ((me.bottom - me.top) / 2);
scaleLabelY = me.top + me.height / 2;
rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
}

Expand Down
23 changes: 23 additions & 0 deletions src/helpers/helpers.math.js
@@ -1,5 +1,7 @@
'use strict';

var helpers = require('./helpers.core');

/**
* @alias Chart.helpers.math
* @namespace
Expand Down Expand Up @@ -28,7 +30,28 @@ var exports = {
return a - b;
}).pop();
return result;
},

log10: Math.log10 || function(x) {
var exponent = Math.log(x) * Math.LOG10E; // Math.LOG10E = 1 / Math.LN10.
// Check for whole powers of 10,
// which due to floating point rounding error should be corrected.
var powerOf10 = Math.round(exponent);
var isPowerOf10 = x === Math.pow(10, powerOf10);

return isPowerOf10 ? powerOf10 : exponent;
}
};

module.exports = exports;

// DEPRECATIONS

/**
* Provided for backward compatibility, use Chart.helpers.math.log10 instead.
* @namespace Chart.helpers.log10
* @deprecated since version 2.9.0
* @todo remove at version 3
* @private
*/
helpers.log10 = exports.log10;
69 changes: 30 additions & 39 deletions src/scales/scale.category.js
Expand Up @@ -63,17 +63,30 @@ module.exports = Scale.extend({
return me.ticks[index - me.minIndex];
},

// Used to get data value locations. Value can either be an index or a numerical value
getPixelForValue: function(value, index, datasetIndex) {
_configure: function() {
var me = this;
var offset = me.options.offset;
var ticks = me.ticks;

Scale.prototype._configure.call(me);

if (!me.isHorizontal()) {
// For backward compatibility, vertical category scale reverse is inverted.
me._reversePixels = !me._reversePixels;
}

if (!ticks) {
return;
}

// 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);
me._startValue = me.minIndex - (offset ? 0.5 : 0);
me._valueRange = Math.max(ticks.length - (offset ? 0 : 1), 1);
},

var isHorizontal = me.isHorizontal();
var valueDimension = (isHorizontal ? me.width : me.height) / offsetAmt;
var valueCategory, labels, idx, pixel;
// Used to get data value locations. Value can either be an index or a numerical value
getPixelForValue: function(value, index, datasetIndex) {
var me = this;
var valueCategory, labels, idx;

if (!isNullOrUndef(index) && !isNullOrUndef(datasetIndex)) {
value = me.chart.data.datasets[datasetIndex].data[index];
Expand All @@ -82,53 +95,31 @@ module.exports = Scale.extend({
// 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.
if (!isNullOrUndef(value)) {
valueCategory = isHorizontal ? value.x : value.y;
valueCategory = me.isHorizontal() ? value.x : value.y;
}
if (valueCategory !== undefined || (value !== undefined && isNaN(index))) {
labels = me._getLabels();
value = helpers.valueOrDefault(valueCategory, value);
idx = labels.indexOf(value);
index = idx !== -1 ? idx : index;
if (isNaN(index)) {
index = value;
}
}

pixel = valueDimension * (index - me.minIndex);

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

return (isHorizontal ? me.left : me.top) + pixel;
return me.getPixelForDecimal((index - me._startValue) / me._valueRange);
},

getPixelForTick: function(index) {
var ticks = this.ticks;
if (index < 0 || index > ticks.length - 1) {
return null;
}
return this.getPixelForValue(ticks[index], index + this.minIndex);
return index < 0 || index > ticks.length - 1
? null
: this.getPixelForValue(ticks[index], index + this.minIndex);
},

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

pixel -= isHorizontal ? me.left : me.top;

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

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

return value + me.minIndex;
var value = Math.round(me._startValue + me.getDecimalForPixel(pixel) * me._valueRange);
return Math.min(Math.max(value, 0), me.ticks.length - 1);
},

getBasePixel: function() {
Expand Down