Chartjs 横柱图 datasetLabel 显示不全问题

190 阅读1分钟

项目中需支持横柱图, 但是横柱图label 长度是动态变化,有时会显示不全,体验不好

初始配置 options


export default {
  type: 'bar',
  data: {
    labels: [
      '0 ~ 0.005',
      '0.005 ~ 0.01',
      '0.01 ~ 0.025',
      '0.025 ~ 0.05',
      '0.05 ~ 0.075',
      '0.075 ~ 0.1',
      '0.1 ~ 0.25',
      '0.25 ~ 0.5',
      '0.5 ~ 0.75',
      '0.75 ~ 1.0',
      '1.0 ~ 2.5',
      '2.5 ~ 5.0',
      '5.0 ~ +Inf',
    ],
    datasets: [
      {
        data: [
          2271, 6232, 18370, 10587, 3137, 2199, 7643, 3223, 3087, 551, 244, 102,
          289,
        ],
      },
    ],
  },
  options: {
    responsive: true,
    maintainAspectRatio: false,
    animation: false,
    plugins: {
      crosshair: {},
      legend: {
        display: false,
      },
      datalabels: {
        anchor: 'end',
        align: 'right',
        color: '#FFCE56',
        offset: '0',
        font: {
          weight: 'bold',
        },
      },
    },
    elements: {
      line: {
        tension: 0,
        borderWidth: 1,
        fill: false,
      },
      point: {
        radius: 0,
        hoverRadius: 5,
        pointStyle: 'circle',
      },
      arc: {
        borderWidth: 0,
      },
    },
    hover: {
      mode: 'index',
      intersect: false,
    },
    interval: 15000,
    scales: {
      yAxes: {
        beginAtZero: true,
        ticks: {
          autoSkip: true,
          autoSkipPadding: 5,
        },
      },
    },
    showLine: true,
    indexAxis: 'y',
    tooltip: {},
  },
  plugins: [
    {
      id: 'datalabels',
      defaults: {
        align: 'center',
        anchor: 'center',
        backgroundColor: null,
        borderColor: null,
        borderRadius: 0,
        borderWidth: 0,
        clamp: false,
        clip: false,
        display: true,
        font: {
          lineHeight: 1.2,
          weight: null,
        },
       //对显示 label 进行 format https://chartjs-plugin-datalabels.netlify.app/guide/formatting.html#data-transformation
      formatter: function (value, context) {
        return DataFormatter.formatterByUnit(unit, value, decimals);
      },
      
        listeners: {},
        offset: '0',// 
        opacity: 1,
        padding: {
          top: 4,
          right: 4,
          bottom: 4,
          left: 4,
        },
        rotation: 0,
        textAlign: 'start',
        textStrokeWidth: 0,
        textShadowBlur: 0,
      },
    },
  ],
};


对显示 label 及 tooltip 进行 format

 // tooltip 进行 format https://www.chartjs.org/docs/latest/configuration/tooltip.html#tooltip-callbacks
  options.plugins.tooltip =  {
      callbacks: {
        label: function (tooltipItem: any) {
          return DataFormatter.formatterByUnit(
            unit,
            tooltipItem?.raw,
            decimals,
          );
        },
      },
    },

针对 datalabel 超出可视区 参考网上自定义的插件 stackoverflow.com/questions/6…

//添加 自定义插件 grace 配置
options.plugins.grace = {
  // grace: '10%', // add percentage of max and min to scale
  grace: 2, // add fixed number to min and max of scale
  hardMax: true, // 这里需设置为 true , 否则会显示不全 set suggestedMin/max or hard min/max
},

整体 配置 plugins 添加插件 grace

import ChartDataLabels from 'chartjs-plugin-datalabels';
plugins =  [
      ChartDataLabels,
{
        id: 'grace',
        beforeLayout: (chart, options, c) => {
          let max = Number.MIN_VALUE;
          let min = Number.MAX_VALUE;
          let grace = options.grace || 0;
          let hardMax = options.hardMax || false;

          chart?.data?.datasets?.forEach((dataset) => {
            max = Math.max(max, Math.max(...dataset.data));
            min = Math.min(min, Math.min(...dataset.data));
          });

          if (typeof grace === 'string' && grace.includes('%')) {
            grace = Number(grace.replace('%', '')) / 100;

            chart.options?.scales?.x?.forEach?.((axe) => {
              if (hardMax) {
                axe.ticks.max = max + max * grace;
                axe.ticks.min = min - min * grace;
              } else {
                axe.ticks.suggestedMax = max + max * grace;
                axe.ticks.suggestedMin = min - min * grace;
              }
            });
          } else if (typeof grace === 'number') {
            chart.options.scales.x.forEach?.((axe) => {
              if (hardMax) {
                axe.ticks.max = max + grace;
                axe.ticks.min = min - grace;
              } else {
                axe.ticks.suggestedMax = max + grace;
                axe.ticks.suggestedMin = min - grace;
              }
            });
          }
        },
      },
      ]

也可以直接预留空间

  options.layout = {
    padding: {
      right: 80,
    },
  };