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

Support object values for bar charts #6323

Merged
merged 4 commits into from Jun 19, 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
90 changes: 51 additions & 39 deletions src/scales/scale.category.js
@@ -1,7 +1,10 @@
'use strict';

var helpers = require('../helpers/index');
var Scale = require('../core/core.scale');

var isNullOrUndef = helpers.isNullOrUndef;

var defaultConfig = {
position: 'bottom'
};
Expand All @@ -10,31 +13,43 @@ module.exports = Scale.extend({
determineDataLimits: function() {
var me = this;
var labels = me._getLabels();
me.minIndex = 0;
me.maxIndex = labels.length - 1;
var ticksOpts = me.options.ticks;
var min = ticksOpts.min;
var max = ticksOpts.max;
var minIndex = 0;
var maxIndex = labels.length - 1;
var findIndex;

if (me.options.ticks.min !== undefined) {
if (min !== undefined) {
// user specified min value
findIndex = labels.indexOf(me.options.ticks.min);
me.minIndex = findIndex !== -1 ? findIndex : me.minIndex;
findIndex = labels.indexOf(min);
if (findIndex >= 0) {
minIndex = findIndex;
}
}

if (me.options.ticks.max !== undefined) {
if (max !== undefined) {
// user specified max value
findIndex = labels.indexOf(me.options.ticks.max);
me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex;
findIndex = labels.indexOf(max);
if (findIndex >= 0) {
maxIndex = findIndex;
}
}

me.min = labels[me.minIndex];
me.max = labels[me.maxIndex];
me.minIndex = minIndex;
me.maxIndex = maxIndex;
me.min = labels[minIndex];
me.max = labels[maxIndex];
},

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);
me.ticks = (minIndex === 0 && maxIndex === labels.length - 1) ? labels : labels.slice(minIndex, maxIndex + 1);
benmccann marked this conversation as resolved.
Show resolved Hide resolved
},

getLabelForIndex: function(index, datasetIndex) {
Expand All @@ -49,61 +64,58 @@ module.exports = Scale.extend({
},

// Used to get data value locations. Value can either be an index or a numerical value
getPixelForValue: function(value, index) {
getPixelForValue: function(value, index, datasetIndex) {
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 offsetAmt = Math.max(me.maxIndex + 1 - me.minIndex - (offset ? 0 : 1), 1);

var isHorizontal = me.isHorizontal();
var valueDimension = (isHorizontal ? me.width : me.height) / offsetAmt;
nagix marked this conversation as resolved.
Show resolved Hide resolved
var valueCategory, labels, idx, pixel;

if (!isNullOrUndef(index) && !isNullOrUndef(datasetIndex)) {
value = me.chart.data.datasets[datasetIndex].data[index];
}

// 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 (!isNullOrUndef(value)) {
valueCategory = isHorizontal ? value.x : value.y;
}
if (valueCategory !== undefined || (value !== undefined && isNaN(index))) {
var labels = me._getLabels();
value = valueCategory || value;
var idx = labels.indexOf(value);
labels = me._getLabels();
value = helpers.valueOrDefault(valueCategory, 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 (isHorizontal ? me.left : me.top) + pixel;
},

getPixelForTick: function(index) {
return this.getPixelForValue(this.ticks[index], index + this.minIndex, null);
return this.getPixelForValue(this.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;
var offsetAmt = Math.max((me._ticks.length - (offset ? 0 : 1)), 1);
var horz = me.isHorizontal();
var valueDimension = (horz ? me.width : me.height) / offsetAmt;

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

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

if (pixel <= 0) {
Expand Down
153 changes: 153 additions & 0 deletions test/specs/scale.category.tests.js
Expand Up @@ -390,4 +390,157 @@ describe('Category scale tests', function() {
expect(yScale.getPixelForValue(0, 1, 0)).toBeCloseToPixel(107);
expect(yScale.getPixelForValue(0, 3, 0)).toBeCloseToPixel(407);
});

it('Should get the correct pixel for an object value when horizontal', function() {
var chart = window.acquireChart({
type: 'line',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: [
{x: 0, y: 10},
{x: 1, y: 5},
{x: 2, y: 0},
{x: 3, y: 25},
{x: 0, y: 78}
]
}],
labels: [0, 1, 2, 3]
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'category',
position: 'bottom'
}],
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});

var xScale = chart.scales.xScale0;
expect(xScale.getPixelForValue({x: 0, y: 10}, 0, 0)).toBeCloseToPixel(29);
expect(xScale.getPixelForValue({x: 3, y: 25}, 3, 0)).toBeCloseToPixel(506);
expect(xScale.getPixelForValue({x: 0, y: 78}, 4, 0)).toBeCloseToPixel(29);
});

it('Should get the correct pixel for an object value when vertical', function() {
var chart = window.acquireChart({
type: 'line',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: [
{x: 0, y: 2},
{x: 1, y: 4},
{x: 2, y: 0},
{x: 3, y: 3},
{x: 0, y: 1}
]
}],
labels: [0, 1, 2, 3],
yLabels: [0, 1, 2, 3, 4]
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'category',
position: 'bottom'
}],
yAxes: [{
id: 'yScale0',
type: 'category',
position: 'left'
}]
}
}
});

var yScale = chart.scales.yScale0;
expect(yScale.getPixelForValue({x: 0, y: 2}, 0, 0)).toBeCloseToPixel(257);
expect(yScale.getPixelForValue({x: 0, y: 1}, 4, 0)).toBeCloseToPixel(144);
});

it('Should get the correct pixel for an object value in a bar chart', function() {
var chart = window.acquireChart({
type: 'bar',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: [
{x: 0, y: 10},
{x: 1, y: 5},
{x: 2, y: 0},
{x: 3, y: 25},
{x: 0, y: 78}
]
}],
labels: [0, 1, 2, 3]
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'category',
position: 'bottom'
}],
yAxes: [{
id: 'yScale0',
type: 'linear'
}]
}
}
});

var xScale = chart.scales.xScale0;
expect(xScale.getPixelForValue(null, 0, 0)).toBeCloseToPixel(89);
expect(xScale.getPixelForValue(null, 3, 0)).toBeCloseToPixel(449);
expect(xScale.getPixelForValue(null, 4, 0)).toBeCloseToPixel(89);
});

it('Should get the correct pixel for an object value in a horizontal bar chart', function() {
var chart = window.acquireChart({
type: 'horizontalBar',
data: {
datasets: [{
xAxisID: 'xScale0',
yAxisID: 'yScale0',
data: [
{x: 10, y: 0},
{x: 5, y: 1},
{x: 0, y: 2},
{x: 25, y: 3},
{x: 78, y: 0}
]
}],
labels: [0, 1, 2, 3]
},
options: {
scales: {
xAxes: [{
id: 'xScale0',
type: 'linear',
position: 'bottom'
}],
yAxes: [{
id: 'yScale0',
type: 'category'
}]
}
}
});

var yScale = chart.scales.yScale0;
expect(yScale.getPixelForValue(null, 0, 0)).toBeCloseToPixel(88);
expect(yScale.getPixelForValue(null, 3, 0)).toBeCloseToPixel(426);
expect(yScale.getPixelForValue(null, 4, 0)).toBeCloseToPixel(88);
});
});