Open jyotidhiman0610 opened 6 years ago
hi @jyotidhiman0610 did you find any solution i am also using ng2-charts but my charts didn't stacked at 100 %
ng2-charts has some additional fiddling to make plugin registration work correctly, once it is hooked in correctly the stacked charts do work.
You'll want to take a look at this issue discussion: https://github.com/valor-software/ng2-charts/issues/752#issuecomment-439060266
This is not a solution but you found a quick solution for use this lib with angular :
stacked-100.lib.ts
import { Chart } from 'chart.js';
/**
Add custom plugins for stacked bar with 100% Y axe. */ export const chartJsRegistererStacked100 = () => { const isObject = function (obj) { const type = typeof obj; return type === 'object' && !!obj; };
const dataValue = function (dataPoint, isHorizontal) { if (isObject(dataPoint)) { return isHorizontal ? dataPoint.x : dataPoint.y; }
return dataPoint;
};
const cloneArray = function (srcAry) { const dstAry = []; const length = srcAry.length;
for (let i = 0; i < length; i++) {
dstAry.push(srcAry[i]);
}
return dstAry;
};
const setOriginalData = function (data) { data.originalData = data.datasets.map(function (dataset) { return cloneArray(dataset.data); }); };
// set calculated rate (xx%) to data.calculatedData const calculateRate = function (data, isHorizontal, precision) { const visibles = data.datasets.map(function (dataset) { if (!dataset._meta) { return true; }
for (const i in dataset._meta) {
return !dataset._meta[i].hidden;
}
});
let datasetDataLength = 0;
if (data && data.datasets && data.datasets[0] && data.datasets[0].data) {
datasetDataLength = data.datasets[0].data.length;
}
const totals = Array.apply(null, new Array(datasetDataLength)).map(function (el, i) {
return data.datasets.reduce(function (sum, dataset, j) {
const key = dataset.stack;
if (!sum[key]) {
sum[key] = 0;
}
sum[key] += Math.abs(dataValue(dataset.data[i], isHorizontal)) * visibles[j];
return sum;
}, {});
});
data.calculatedData = data.datasets.map(function (dataset, i) {
// tslint:disable-next-line:no-shadowed-variable
return dataset.data.map(function (val, i) {
const total = totals[i][dataset.stack];
const dv = dataValue(val, isHorizontal);
return dv && total ? round(dv / total, precision) : 0;
});
});
};
const getPrecision = function (pluginOptions) { // return the (validated) configured precision from pluginOptions or default 1 const defaultPrecision = 1; if (!pluginOptions.hasOwnProperty('precision')) { return defaultPrecision; } if (!pluginOptions.precision) { return defaultPrecision; } const optionsPrecision = Math.floor(pluginOptions.precision); if (isNaN(optionsPrecision)) { return defaultPrecision; } if (optionsPrecision < 0 || optionsPrecision > 16) { return defaultPrecision; } return optionsPrecision; };
const round = function (value, precision) { const multiplicator = Math.pow(10, precision); return Math.round(value 100 multiplicator) / multiplicator; };
const tooltipLabel = function (isHorizontal) { return function (tooltipItem, data) { const datasetIndex = tooltipItem.datasetIndex; const index = tooltipItem.index; const originalValue = data.originalData[datasetIndex][index]; const rateValue = data.calculatedData[datasetIndex][index];
return '' + rateValue + '% (' + dataValue(originalValue, isHorizontal) + ')';
};
};
const reflectData = function (srcData, datasets) { if (!srcData) { return; }
srcData.forEach(function (data, i) {
datasets[i].data = data;
});
};
// tslint:disable-next-line:no-shadowed-variable const isHorizontalChart = function (chartInstance) { return chartInstance.config.type === 'horizontalBar'; };
// tslint:disable-next-line:no-shadowed-variable const Stacked100Plugin = { id: 'stacked100',
// tslint:disable-next-line:no-shadowed-variable
beforeInit: function (chartInstance) {
if (!chartInstance.options.stacked100 || !chartInstance.options.stacked100.enable) {
return;
}
const xAxes = chartInstance.options.scales.xAxes;
const yAxes = chartInstance.options.scales.yAxes;
const isVertical = chartInstance.config.type === 'bar' || chartInstance.config.type === 'line';
[xAxes, yAxes].forEach(function (axes) {
axes.forEach(function (hash) {
hash.stacked = true;
});
});
(isVertical ? yAxes : xAxes).forEach(function (hash) {
if (!hash.ticks.min) {
const hasNegative = chartInstance.data.datasets.some(function (dataset) {
return dataset.data.some(function (value) {
return value < 0;
});
});
hash.ticks.min = hasNegative ? -100 : 0;
}
if (!hash.ticks.max) {
hash.ticks.max = 100;
}
});
// Replace tooltips
if (chartInstance.options.stacked100.hasOwnProperty('replaceTooltipLabel') && !chartInstance.options.stacked100.replaceTooltipLabel) {
return;
}
chartInstance.options.tooltips.callbacks.label = tooltipLabel(isHorizontalChart(chartInstance));
},
// tslint:disable-next-line:no-shadowed-variable
beforeDatasetsUpdate: function (chartInstance) {
if (!chartInstance.options.stacked100 || !chartInstance.options.stacked100.enable) {
return;
}
setOriginalData(chartInstance.data);
const precision = getPrecision(chartInstance.options.stacked100);
calculateRate(chartInstance.data, isHorizontalChart(chartInstance), precision);
reflectData(chartInstance.data.calculatedData, chartInstance.data.datasets);
},
// tslint:disable-next-line:no-shadowed-variable
afterDatasetsUpdate: function (chartInstance) {
if (!chartInstance.options.stacked100 || !chartInstance.options.stacked100.enable) {
return;
}
reflectData(chartInstance.data.originalData, chartInstance.data.datasets);
}
};
if (!(Chart.pluginService as any).getAll().filter(p => p.id === 'stacked100')[0]) { Chart.pluginService.register(Stacked100Plugin); } };
* and on your chart component :
```js
ngAfterViewInit() {
const canvas: any = document.getElementById('canvas_' + this.guid);
const ctx: HTMLCanvasElement = canvas.getContext('2d');
// bug fix chartjs/angular. registerer stacked100 plugins
chartJsRegistererStacked100();
const options: any | Chart.ChartConfiguration = {
type: this.chart.type,
data: this.chart.data,
options: {
stacked100: {
enable: true,
replaceTooltipLabel: true,
}
},
};
const myBar = new Chart(ctx, options);
}
/!\ chartjs-plugin-stacked100's options is not on "plugins" attribut but on "options" attribut !
I installed the plugin as specified in the docs, I am using ng2-charts with following options:
public barChartOptions = { plugins: { stacked100: { enable: true }, }, legend: { display: true, position: 'bottom', }, scales: { xAxes: [{ display: true, stacked: true }], yAxes: [{ display: false, stacked: true }], }, };
No percentages are shown for me. The chart still displays value options.