GithubHelp home page GithubHelp logo

Comments (3)

gantispam avatar gantispam commented on May 21, 2024 1

This is not a solution but you found a quick solution for use this lib with angular :

  • Create new file stacked-100.lib.ts
import { Chart } from 'chart.js';

/**
 * Chart.JS and Angular can be incompatible.
 * This function is inspired of lib : https://github.com/y-takey/chartjs-plugin-stacked100
 *
 * 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 :
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 !

from chartjs-plugin-stacked100.

ankitp047 avatar ankitp047 commented on May 21, 2024

hi @jyotidhiman0610
did you find any solution i am also using ng2-charts but my charts didn't stacked at 100 %

from chartjs-plugin-stacked100.

srmccray avatar srmccray commented on May 21, 2024

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:
valor-software/ng2-charts#752 (comment)

from chartjs-plugin-stacked100.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.