ChartJS 如何在图表js中将正值定位在堆叠条形图的顶部,将负值定位在底部

siv3szwd  于 2023-08-05  发布在  Chart.js
关注(0)|答案(2)|浏览(179)

formatter函数给出了每组堆叠条形图的总和,我试图执行datalabels,如果总和为正,则将其定位在上,如果总和为负,则将其定位在下。请任何帮助将不胜感激。


的数据

datalabels: {
    anchor: (context) =>{
        const anchor = [];
        let sum = ?;
        
        if(parseFloat(sum) >=0){
            anchor.push('end');
        }else{
            anchor.push('start');
        }
        return anchor;
    },
    align: (context) =>{
        const align = [];
        let sum = ?;

        if(parseFloat(sum) >=0){
            align.push('end');
        }else{
            align.push('bottom');
        }
        return align;

    },
    formatter:(value, context) =>{
        const datasetArray = [];
        context.chart.data.datasets.forEach((dataset) =>{
            if(dataset.data[context.dataIndex] != undefined){
                datasetArray.push(dataset.data[context.dataIndex]);
            }
            
        });
        
        function totalSum(total, datapoint){                                           
            return +total + +datapoint;
        }
        
        let sum = datasetArray.reduce(totalSum);
        if(context.datasetIndex === datasetArray.length - 1){
            return parseFloat(sum).toFixed(2) ;
        }else{
            return '';
        }
    },
}

字符串

jtoj6r0c

jtoj6r0c1#

目前还不清楚这些酒吧是如何堆叠的-有许多未知的选择。基于图像图表的视觉外观的可能组合可以是以下:

const N = 10;
const dataGenerator = (plus = 600, minus = 400, pNull = 1) =>
    Array.from({length: N}, ()=>Math.random() < pNull ?
        Math.round(Math.random()*(plus+minus)-minus)/4 : null)
const ctx1 = document.getElementById('chart1');
new Chart(ctx1, {
    type: "bar",
    plugins: [ChartDataLabels],
    data: {
        labels: Array.from({length: N}, (_, i)=>'l'+(i+1)),
        datasets: [
            {
                data: dataGenerator(),
                stack: 'a',
            },
            {
                data: dataGenerator() ,
                stack: 'a',
            },
            {
                data: dataGenerator(100, 50, 0.5),
                stack: 'a',
            },
        ]
    },
    options: {
        indexAxis: 'x',
        layout: {
            padding: {
                top: 20,
                bottom: 20
            }
        },
        animation: {
            duration: 0
        },
        scales: {
            x: {
                ticks:{
                    display: false
                }
            },
            y: {
                stacked: true,
                beginAtZero: true
            }
        },
        plugins:{
            legend:{
                display: false
            },
            datalabels:{
                formatter: (value, context) => {
                    const {dataIndex, datasetIndex, chart} = context;
                    const dataForDataIndex = chart.data.datasets.map(
                        dataset=>dataset.data[dataIndex] ?? 0
                    );
                    const total = dataForDataIndex.reduce((s, x)=>s+x)
                    // the index of the dataset that contains the last point (at dataIndex)
                    // with the same sign as the total - that is the one that should carry
                    // the total label
                    const datasetIndexLast = dataForDataIndex.findLastIndex(x => x * total > 0);
                    context.total = total;
                    return datasetIndexLast === datasetIndex ? total.toFixed(2) : null
                },
                anchor: (context) => {
                    return context.total > 0 ? 'end' : 'start'
                },
                align: (context) => {
                    return context.total > 0 ? 'top' : 'bottom';
                },

                clip: false
            }
        }
    }
});

个字符
这背后的想法是为数据集中的所有条启用数据标签,但选择正确定位的一个来表示formatter的总和-即最后一个数据集,其值(对于当前dataIndex)与总和具有相同的符号。如果使用order选项,情况可能会有所不同。
这段代码还使用了这样一个事实,即context对象在formatteralignanchor方法之间是共享的,* 对于同一个datasetIndex *,formatter总是第一个--如果formatter返回null,则其他方法甚至不会被调用。因此,它将当前datasetIndex的和保存在context对象中,以供调用alignanchor的唯一一个点(每个datasetIndex)使用。对于一个更安全的解决方案,即不使用这个未记录的事实,可以重新计算alignanchor中的总和,或者使用外部对象缓存总和,这可以是一种通过只计算一次总和来优化计算的解决方案,第一次为数据集调用formatter

kyks70gy

kyks70gy2#

您可以使用chartjs-plugin-datalabels,如here所示。

Chart.defaults.set('plugins.datalabels', {
  color: '#FE777B'
});

var chart = new Chart(ctx, {
  options: {
    plugins: {
      // Change options for ALL labels of THIS CHART
      datalabels: {
        color: '#36A2EB',
        anchor: ()=>/*your condition here*/
      }
    }
  },
  data: {
    datasets: [{
      // Change options only for labels of THIS DATASET
      datalabels: {
        color: '#FFCE56'
      }
    }]
  }
});

字符串
同时检出定位属性。

相关问题