608 lines
20 KiB
JavaScript
608 lines
20 KiB
JavaScript
"use strict";
|
|
|
|
module.exports = function(Chart) {
|
|
|
|
var helpers = Chart.helpers;
|
|
|
|
Chart.defaults.bar = {
|
|
hover: {
|
|
mode: "label"
|
|
},
|
|
|
|
scales: {
|
|
xAxes: [{
|
|
type: "category",
|
|
|
|
// Specific to Bar Controller
|
|
categoryPercentage: 0.8,
|
|
barPercentage: 0.9,
|
|
|
|
// grid line settings
|
|
gridLines: {
|
|
offsetGridLines: true
|
|
}
|
|
}],
|
|
yAxes: [{
|
|
type: "linear"
|
|
}]
|
|
}
|
|
};
|
|
|
|
Chart.controllers.bar = Chart.DatasetController.extend({
|
|
initialize: function(chart, datasetIndex) {
|
|
Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);
|
|
|
|
// Use this to indicate that this is a bar dataset.
|
|
this.getMeta().bar = true;
|
|
},
|
|
// Get the number of datasets that display bars. We use this to correctly calculate the bar width
|
|
getBarCount: function getBarCount() {
|
|
var barCount = 0;
|
|
helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
|
|
var meta = this.chart.getDatasetMeta(datasetIndex);
|
|
if (meta.bar && this.chart.isDatasetVisible(datasetIndex)) {
|
|
++barCount;
|
|
}
|
|
}, this);
|
|
return barCount;
|
|
},
|
|
|
|
addElements: function() {
|
|
var meta = this.getMeta();
|
|
helpers.each(this.getDataset().data, function(value, index) {
|
|
meta.data[index] = meta.data[index] || new Chart.elements.Rectangle({
|
|
_chart: this.chart.chart,
|
|
_datasetIndex: this.index,
|
|
_index: index
|
|
});
|
|
}, this);
|
|
},
|
|
|
|
addElementAndReset: function(index) {
|
|
var rectangle = new Chart.elements.Rectangle({
|
|
_chart: this.chart.chart,
|
|
_datasetIndex: this.index,
|
|
_index: index
|
|
});
|
|
|
|
var numBars = this.getBarCount();
|
|
|
|
// Add to the points array and reset it
|
|
this.getMeta().data.splice(index, 0, rectangle);
|
|
this.updateElement(rectangle, index, true, numBars);
|
|
},
|
|
|
|
update: function update(reset) {
|
|
var numBars = this.getBarCount();
|
|
|
|
helpers.each(this.getMeta().data, function(rectangle, index) {
|
|
this.updateElement(rectangle, index, reset, numBars);
|
|
}, this);
|
|
},
|
|
|
|
updateElement: function updateElement(rectangle, index, reset, numBars) {
|
|
var meta = this.getMeta();
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
|
|
var yScalePoint;
|
|
|
|
if (yScale.min < 0 && yScale.max < 0) {
|
|
// all less than 0. use the top
|
|
yScalePoint = yScale.getPixelForValue(yScale.max);
|
|
} else if (yScale.min > 0 && yScale.max > 0) {
|
|
yScalePoint = yScale.getPixelForValue(yScale.min);
|
|
} else {
|
|
yScalePoint = yScale.getPixelForValue(0);
|
|
}
|
|
|
|
helpers.extend(rectangle, {
|
|
// Utility
|
|
_chart: this.chart.chart,
|
|
_xScale: xScale,
|
|
_yScale: yScale,
|
|
_datasetIndex: this.index,
|
|
_index: index,
|
|
|
|
|
|
// Desired view properties
|
|
_model: {
|
|
x: this.calculateBarX(index, this.index),
|
|
y: reset ? yScalePoint : this.calculateBarY(index, this.index),
|
|
|
|
// Tooltip
|
|
label: this.chart.data.labels[index],
|
|
datasetLabel: this.getDataset().label,
|
|
|
|
// Appearance
|
|
base: reset ? yScalePoint : this.calculateBarBase(this.index, index),
|
|
width: this.calculateBarWidth(numBars),
|
|
backgroundColor: rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor),
|
|
borderSkipped: rectangle.custom && rectangle.custom.borderSkipped ? rectangle.custom.borderSkipped : this.chart.options.elements.rectangle.borderSkipped,
|
|
borderColor: rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor),
|
|
borderWidth: rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth)
|
|
}
|
|
});
|
|
rectangle.pivot();
|
|
},
|
|
|
|
calculateBarBase: function(datasetIndex, index) {
|
|
var meta = this.getMeta();
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
|
|
var base = 0;
|
|
|
|
if (yScale.options.stacked) {
|
|
|
|
var value = this.chart.data.datasets[datasetIndex].data[index];
|
|
|
|
if (value < 0) {
|
|
for (var i = 0; i < datasetIndex; i++) {
|
|
var negDS = this.chart.data.datasets[i];
|
|
var negDSMeta = this.chart.getDatasetMeta(i);
|
|
if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {
|
|
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
|
|
}
|
|
}
|
|
} else {
|
|
for (var j = 0; j < datasetIndex; j++) {
|
|
var posDS = this.chart.data.datasets[j];
|
|
var posDSMeta = this.chart.getDatasetMeta(j);
|
|
if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(j)) {
|
|
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return yScale.getPixelForValue(base);
|
|
}
|
|
|
|
base = yScale.getPixelForValue(yScale.min);
|
|
|
|
if (yScale.beginAtZero || ((yScale.min <= 0 && yScale.max >= 0) || (yScale.min >= 0 && yScale.max <= 0))) {
|
|
base = yScale.getPixelForValue(0, 0);
|
|
//base += yScale.options.gridLines.lineWidth;
|
|
} else if (yScale.min < 0 && yScale.max < 0) {
|
|
// All values are negative. Use the top as the base
|
|
base = yScale.getPixelForValue(yScale.max);
|
|
}
|
|
|
|
return base;
|
|
|
|
},
|
|
|
|
getRuler: function() {
|
|
var meta = this.getMeta();
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
var datasetCount = this.getBarCount();
|
|
|
|
var tickWidth = (function() {
|
|
var min = xScale.getPixelForTick(1) - xScale.getPixelForTick(0);
|
|
for (var i = 2; i < this.getDataset().data.length; i++) {
|
|
min = Math.min(xScale.getPixelForTick(i) - xScale.getPixelForTick(i - 1), min);
|
|
}
|
|
return min;
|
|
}).call(this);
|
|
var categoryWidth = tickWidth * xScale.options.categoryPercentage;
|
|
var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;
|
|
var fullBarWidth = categoryWidth / datasetCount;
|
|
|
|
if (xScale.ticks.length !== this.chart.data.labels.length) {
|
|
var perc = xScale.ticks.length / this.chart.data.labels.length;
|
|
fullBarWidth = fullBarWidth * perc;
|
|
}
|
|
|
|
var barWidth = fullBarWidth * xScale.options.barPercentage;
|
|
var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);
|
|
|
|
return {
|
|
datasetCount: datasetCount,
|
|
tickWidth: tickWidth,
|
|
categoryWidth: categoryWidth,
|
|
categorySpacing: categorySpacing,
|
|
fullBarWidth: fullBarWidth,
|
|
barWidth: barWidth,
|
|
barSpacing: barSpacing
|
|
};
|
|
},
|
|
|
|
calculateBarWidth: function() {
|
|
var xScale = this.getScaleForId(this.getMeta().xAxisID);
|
|
var ruler = this.getRuler();
|
|
return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;
|
|
},
|
|
|
|
// Get bar index from the given dataset index accounting for the fact that not all bars are visible
|
|
getBarIndex: function(datasetIndex) {
|
|
var barIndex = 0;
|
|
var meta, j;
|
|
|
|
for (j = 0; j < datasetIndex; ++j) {
|
|
meta = this.chart.getDatasetMeta(j);
|
|
if (meta.bar && this.chart.isDatasetVisible(j)) {
|
|
++barIndex;
|
|
}
|
|
}
|
|
|
|
return barIndex;
|
|
},
|
|
|
|
calculateBarX: function(index, datasetIndex) {
|
|
var meta = this.getMeta();
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var barIndex = this.getBarIndex(datasetIndex);
|
|
|
|
var ruler = this.getRuler();
|
|
var leftTick = xScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);
|
|
leftTick -= this.chart.isCombo ? (ruler.tickWidth / 2) : 0;
|
|
|
|
if (xScale.options.stacked) {
|
|
return leftTick + (ruler.categoryWidth / 2) + ruler.categorySpacing;
|
|
}
|
|
|
|
return leftTick +
|
|
(ruler.barWidth / 2) +
|
|
ruler.categorySpacing +
|
|
(ruler.barWidth * barIndex) +
|
|
(ruler.barSpacing / 2) +
|
|
(ruler.barSpacing * barIndex);
|
|
},
|
|
|
|
calculateBarY: function(index, datasetIndex) {
|
|
var meta = this.getMeta();
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
|
|
var value = this.getDataset().data[index];
|
|
|
|
if (yScale.options.stacked) {
|
|
|
|
var sumPos = 0,
|
|
sumNeg = 0;
|
|
|
|
for (var i = 0; i < datasetIndex; i++) {
|
|
var ds = this.chart.data.datasets[i];
|
|
var dsMeta = this.chart.getDatasetMeta(i);
|
|
if (dsMeta.bar && dsMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {
|
|
if (ds.data[index] < 0) {
|
|
sumNeg += ds.data[index] || 0;
|
|
} else {
|
|
sumPos += ds.data[index] || 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (value < 0) {
|
|
return yScale.getPixelForValue(sumNeg + value);
|
|
} else {
|
|
return yScale.getPixelForValue(sumPos + value);
|
|
}
|
|
}
|
|
|
|
return yScale.getPixelForValue(value);
|
|
},
|
|
|
|
draw: function(ease) {
|
|
var easingDecimal = ease || 1;
|
|
helpers.each(this.getMeta().data, function(rectangle, index) {
|
|
var d = this.getDataset().data[index];
|
|
if (d !== null && d !== undefined && !isNaN(d)) {
|
|
rectangle.transition(easingDecimal).draw();
|
|
}
|
|
}, this);
|
|
},
|
|
|
|
setHoverStyle: function(rectangle) {
|
|
var dataset = this.chart.data.datasets[rectangle._datasetIndex];
|
|
var index = rectangle._index;
|
|
|
|
rectangle._model.backgroundColor = rectangle.custom && rectangle.custom.hoverBackgroundColor ? rectangle.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.color(rectangle._model.backgroundColor).saturate(0.5).darken(0.1).rgbString());
|
|
rectangle._model.borderColor = rectangle.custom && rectangle.custom.hoverBorderColor ? rectangle.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.color(rectangle._model.borderColor).saturate(0.5).darken(0.1).rgbString());
|
|
rectangle._model.borderWidth = rectangle.custom && rectangle.custom.hoverBorderWidth ? rectangle.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, rectangle._model.borderWidth);
|
|
},
|
|
|
|
removeHoverStyle: function(rectangle) {
|
|
var dataset = this.chart.data.datasets[rectangle._datasetIndex];
|
|
var index = rectangle._index;
|
|
|
|
rectangle._model.backgroundColor = rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor);
|
|
rectangle._model.borderColor = rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor);
|
|
rectangle._model.borderWidth = rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth);
|
|
}
|
|
|
|
});
|
|
|
|
|
|
// including horizontalBar in the bar file, instead of a file of its own
|
|
// it extends bar (like pie extends doughnut)
|
|
Chart.defaults.horizontalBar = {
|
|
hover: {
|
|
mode: "label"
|
|
},
|
|
|
|
scales: {
|
|
xAxes: [{
|
|
type: "linear",
|
|
position: "bottom"
|
|
}],
|
|
yAxes: [{
|
|
position: "left",
|
|
type: "category",
|
|
|
|
// Specific to Horizontal Bar Controller
|
|
categoryPercentage: 0.8,
|
|
barPercentage: 0.9,
|
|
|
|
// grid line settings
|
|
gridLines: {
|
|
offsetGridLines: true
|
|
}
|
|
}]
|
|
},
|
|
};
|
|
|
|
Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
|
|
updateElement: function updateElement(rectangle, index, reset, numBars) {
|
|
var meta = this.getMeta();
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
|
|
var xScalePoint;
|
|
|
|
if (xScale.min < 0 && xScale.max < 0) {
|
|
// all less than 0. use the right
|
|
xScalePoint = xScale.getPixelForValue(xScale.max);
|
|
} else if (xScale.min > 0 && xScale.max > 0) {
|
|
xScalePoint = xScale.getPixelForValue(xScale.min);
|
|
} else {
|
|
xScalePoint = xScale.getPixelForValue(0);
|
|
}
|
|
|
|
helpers.extend(rectangle, {
|
|
// Utility
|
|
_chart: this.chart.chart,
|
|
_xScale: xScale,
|
|
_yScale: yScale,
|
|
_datasetIndex: this.index,
|
|
_index: index,
|
|
|
|
// Desired view properties
|
|
_model: {
|
|
x: reset ? xScalePoint : this.calculateBarX(index, this.index),
|
|
y: this.calculateBarY(index, this.index),
|
|
|
|
// Tooltip
|
|
label: this.chart.data.labels[index],
|
|
datasetLabel: this.getDataset().label,
|
|
|
|
// Appearance
|
|
base: reset ? xScalePoint : this.calculateBarBase(this.index, index),
|
|
height: this.calculateBarHeight(numBars),
|
|
backgroundColor: rectangle.custom && rectangle.custom.backgroundColor ? rectangle.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().backgroundColor, index, this.chart.options.elements.rectangle.backgroundColor),
|
|
borderSkipped: rectangle.custom && rectangle.custom.borderSkipped ? rectangle.custom.borderSkipped : this.chart.options.elements.rectangle.borderSkipped,
|
|
borderColor: rectangle.custom && rectangle.custom.borderColor ? rectangle.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().borderColor, index, this.chart.options.elements.rectangle.borderColor),
|
|
borderWidth: rectangle.custom && rectangle.custom.borderWidth ? rectangle.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().borderWidth, index, this.chart.options.elements.rectangle.borderWidth)
|
|
},
|
|
|
|
draw: function () {
|
|
|
|
var ctx = this._chart.ctx;
|
|
var vm = this._view;
|
|
|
|
var halfHeight = vm.height / 2,
|
|
topY = vm.y - halfHeight,
|
|
bottomY = vm.y + halfHeight,
|
|
right = vm.base - (vm.base - vm.x),
|
|
halfStroke = vm.borderWidth / 2;
|
|
|
|
// Canvas doesn't allow us to stroke inside the width so we can
|
|
// adjust the sizes to fit if we're setting a stroke on the line
|
|
if (vm.borderWidth) {
|
|
topY += halfStroke;
|
|
bottomY -= halfStroke;
|
|
right += halfStroke;
|
|
}
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.fillStyle = vm.backgroundColor;
|
|
ctx.strokeStyle = vm.borderColor;
|
|
ctx.lineWidth = vm.borderWidth;
|
|
|
|
// Corner points, from bottom-left to bottom-right clockwise
|
|
// | 1 2 |
|
|
// | 0 3 |
|
|
var corners = [
|
|
[vm.base, bottomY],
|
|
[vm.base, topY],
|
|
[right, topY],
|
|
[right, bottomY]
|
|
];
|
|
|
|
// Find first (starting) corner with fallback to 'bottom'
|
|
var borders = ['bottom', 'left', 'top', 'right'];
|
|
var startCorner = borders.indexOf(vm.borderSkipped, 0);
|
|
if (startCorner === -1)
|
|
startCorner = 0;
|
|
|
|
function cornerAt(index) {
|
|
return corners[(startCorner + index) % 4];
|
|
}
|
|
|
|
// Draw rectangle from 'startCorner'
|
|
ctx.moveTo.apply(ctx, cornerAt(0));
|
|
for (var i = 1; i < 4; i++)
|
|
ctx.lineTo.apply(ctx, cornerAt(i));
|
|
|
|
ctx.fill();
|
|
if (vm.borderWidth) {
|
|
ctx.stroke();
|
|
}
|
|
},
|
|
|
|
inRange: function (mouseX, mouseY) {
|
|
var vm = this._view;
|
|
var inRange = false;
|
|
|
|
if (vm) {
|
|
if (vm.x < vm.base) {
|
|
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);
|
|
} else {
|
|
inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);
|
|
}
|
|
}
|
|
|
|
return inRange;
|
|
}
|
|
});
|
|
|
|
rectangle.pivot();
|
|
},
|
|
|
|
calculateBarBase: function (datasetIndex, index) {
|
|
var meta = this.getMeta();
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
|
|
var base = 0;
|
|
|
|
if (xScale.options.stacked) {
|
|
|
|
var value = this.chart.data.datasets[datasetIndex].data[index];
|
|
|
|
if (value < 0) {
|
|
for (var i = 0; i < datasetIndex; i++) {
|
|
var negDS = this.chart.data.datasets[i];
|
|
var negDSMeta = this.chart.getDatasetMeta(i);
|
|
if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {
|
|
base += negDS.data[index] < 0 ? negDS.data[index] : 0;
|
|
}
|
|
}
|
|
} else {
|
|
for (var j = 0; j < datasetIndex; j++) {
|
|
var posDS = this.chart.data.datasets[j];
|
|
var posDSMeta = this.chart.getDatasetMeta(j);
|
|
if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(j)) {
|
|
base += posDS.data[index] > 0 ? posDS.data[index] : 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return xScale.getPixelForValue(base);
|
|
}
|
|
|
|
base = xScale.getPixelForValue(xScale.min);
|
|
|
|
if (xScale.beginAtZero || ((xScale.min <= 0 && xScale.max >= 0) || (xScale.min >= 0 && xScale.max <= 0))) {
|
|
base = xScale.getPixelForValue(0, 0);
|
|
} else if (xScale.min < 0 && xScale.max < 0) {
|
|
// All values are negative. Use the right as the base
|
|
base = xScale.getPixelForValue(xScale.max);
|
|
}
|
|
|
|
return base;
|
|
},
|
|
|
|
getRuler: function () {
|
|
var meta = this.getMeta();
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
var datasetCount = this.getBarCount();
|
|
|
|
var tickHeight = (function () {
|
|
var min = yScale.getPixelForTick(1) - yScale.getPixelForTick(0);
|
|
for (var i = 2; i < this.getDataset().data.length; i++) {
|
|
min = Math.min(yScale.getPixelForTick(i) - yScale.getPixelForTick(i - 1), min);
|
|
}
|
|
return min;
|
|
}).call(this);
|
|
var categoryHeight = tickHeight * yScale.options.categoryPercentage;
|
|
var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;
|
|
var fullBarHeight = categoryHeight / datasetCount;
|
|
|
|
if (yScale.ticks.length !== this.chart.data.labels.length) {
|
|
var perc = yScale.ticks.length / this.chart.data.labels.length;
|
|
fullBarHeight = fullBarHeight * perc;
|
|
}
|
|
|
|
var barHeight = fullBarHeight * yScale.options.barPercentage;
|
|
var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);
|
|
|
|
return {
|
|
datasetCount: datasetCount,
|
|
tickHeight: tickHeight,
|
|
categoryHeight: categoryHeight,
|
|
categorySpacing: categorySpacing,
|
|
fullBarHeight: fullBarHeight,
|
|
barHeight: barHeight,
|
|
barSpacing: barSpacing,
|
|
};
|
|
},
|
|
|
|
calculateBarHeight: function () {
|
|
var yScale = this.getScaleForId(this.getMeta().yAxisID);
|
|
var ruler = this.getRuler();
|
|
return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;
|
|
},
|
|
|
|
calculateBarX: function (index, datasetIndex) {
|
|
var meta = this.getMeta();
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
|
|
var value = this.getDataset().data[index];
|
|
|
|
if (xScale.options.stacked) {
|
|
|
|
var sumPos = 0,
|
|
sumNeg = 0;
|
|
|
|
for (var i = 0; i < datasetIndex; i++) {
|
|
var ds = this.chart.data.datasets[i];
|
|
var dsMeta = this.chart.getDatasetMeta(i);
|
|
if (dsMeta.bar && dsMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {
|
|
if (ds.data[index] < 0) {
|
|
sumNeg += ds.data[index] || 0;
|
|
} else {
|
|
sumPos += ds.data[index] || 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (value < 0) {
|
|
return xScale.getPixelForValue(sumNeg + value);
|
|
} else {
|
|
return xScale.getPixelForValue(sumPos + value);
|
|
}
|
|
}
|
|
|
|
return xScale.getPixelForValue(value);
|
|
},
|
|
|
|
calculateBarY: function (index, datasetIndex) {
|
|
var meta = this.getMeta();
|
|
var yScale = this.getScaleForId(meta.yAxisID);
|
|
var xScale = this.getScaleForId(meta.xAxisID);
|
|
var barIndex = this.getBarIndex(datasetIndex);
|
|
|
|
var ruler = this.getRuler();
|
|
var topTick = yScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);
|
|
topTick -= this.chart.isCombo ? (ruler.tickHeight / 2) : 0;
|
|
|
|
if (yScale.options.stacked) {
|
|
return topTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;
|
|
}
|
|
|
|
return topTick +
|
|
(ruler.barHeight / 2) +
|
|
ruler.categorySpacing +
|
|
(ruler.barHeight * barIndex) +
|
|
(ruler.barSpacing / 2) +
|
|
(ruler.barSpacing * barIndex);
|
|
}
|
|
});
|
|
};
|