mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Support object values for bar charts (#6323)
* Support object values for bar charts * Check if null or undefined * Refactor category scale code * Make isNullOrUndef global
This commit is contained in:
parent
b31980edab
commit
bb5f12ad2a
@ -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'
|
||||
};
|
||||
@ -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);
|
||||
},
|
||||
|
||||
getLabelForIndex: function(index, datasetIndex) {
|
||||
@ -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;
|
||||
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) {
|
||||
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user