Chart.js - 增加图例和图表之间的间距

问题描述 投票:0回答:13

我有一个条形图,我在其中绘制了 3 条垂直线,每条垂直线的顶部都有自己的标签。我希望这些标签位于 y 轴顶部上方(示例中高于 30% 线)但位于图例下方。我不知道如何增加顶部图例和图表之间的空间,以便我可以让我的垂直线标签(15、24 和 33)脱离图表本身但在图例下方。有什么想法吗?

chart.js chart.js2
13个回答
44
投票

如果你想在所有图表中增加间距,你可以在创建之前放置这段代码:

Chart.Legend.prototype.afterFit = function() {
    this.height = this.height + 50;
};

当然,我没有尝试,但我认为您可以更改它(或复制之前的原始 Chart 对象,以保留原始填充)。

再见,


35
投票

如果您想在图例下方应用填充仅适用于您应用中的某些图表

ChartJS >= 2.1.0

Chart.plugins.register({
  id: 'paddingBelowLegends',
  beforeInit: function(chart, options) {
    chart.legend.afterFit = function() {
      this.height = this.height + 50;
    };
  }
});

// ----------------------------------
// disable the plugin only for charts
// where you DO NOT WANT the padding
// ----------------------------------

// for raw ChartJS use:
var chart = new Chart(ctx, {
  config: {
    plugins: {
      paddingBelowLegends: false
    }
  }
});

// for angular-chartjs:
$scope.myChart.options.plugins = { paddingBelowLegends: false }
// then in template:
// <canvas class="chart ..." chart-options="myChart.options" ... />

ChartJS >= 2.5.0

支持每个图表的特定插件,应该可以做到:

var chart = new Chart(ctx, {
  plugins: [{
    beforeInit: function(chart, options) {
      chart.legend.afterFit = function() {
        this.height = this.height + 50;
      };
    }
  }]
});

See ChartJS 文档 + 灵感来自this other answer


20
投票

不幸的是,由于没有配置选项来处理这个问题,您获得所需结果的唯一方法是扩展 Chart.Legend 并实施

afterFit()
回调。

这里有一个快速的codepen展示了如何做到这一点。要更改间距,只需更改第 9 行中的值(当前设置为 50)。此外,这当然只适用于顶部的图例。希望这个示例足够清楚,以便您在想将图例移到其他地方时进行修改。


18
投票

如果有人想知道为什么

afterFit
解决方案在 Chart.js 3.3.0 中不起作用,那是因为
afterFit
函数已从图例插件中删除。

如果你想通过利用

fit
功能来完成这项工作,你可以尝试这个 hacky 解决方案/解决方法:

const plugin = {
  beforeInit(chart) {
    // Get a reference to the original fit function
    const originalFit = chart.legend.fit;

    // Override the fit function
    chart.legend.fit = function fit() {
      // Call the original function and bind scope in order to use `this` correctly inside it
      originalFit.bind(chart.legend)();
      // Change the height as suggested in other answers
      this.height += 15;
    }
  }
}

我知道这不是一个理想的解决方案,但在我们对这个图例填充有原生支持之前,恐怕这是我们现在能做的最好的了。


9
投票

经过 2 天的研究,这对我有所帮助。

Chart.Legend.prototype.afterFit = function() {
    this.height = this.height + 50;
};

在 module.ts 文件中更新


7
投票

我正在使用 react-chartjs-2(但这只是一个端口并使用相同的配置对象)并且我能够通过更改嵌套在图例配置上的标签配置来实现:

chartOptions = {
  legend: {
    labels: {
      padding: 50 -> this one.
    }
  },

您可以在这里查看房产描述: https://www.chartjs.org/docs/latest/configuration/legend.html

希望有帮助。


2
投票

我已经在我的 react(react-chartjs-2) 项目中尝试了上述方法,但没有成功。在这里,我有一种不同的方法,比如在图表外创建自定义图例。所以你可以更好地控制它

  1. 隐藏默认图例
  2. 使用任何 ref 方法获取图例对象。
  3. 循环并使用 html 和 css 制作自定义图例。
  4. 样本codesanbox

我知道 OP 与 reactjs 组件无关,但由于这是一个常见问题,它会对某人有所帮助。

原文参考

.


1
投票

对于

ng2-charts@^3.1.0
,在这个answer之后加上一个:

this.options.labels.padding = 40;
//this.height += 15;

title.padding
配置(这将在图表下方创建一个不可见的标题,所以它有点 hacky):

    plugins: {
      legend: {
        display: true,
        position: 'bottom',
        title: {
          display: true,
          padding: 10,
        },

堆栈闪电战


0
投票

搜索 chart.js 文件后,我发现标签栏的高度定义在那里

height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight)

this.height = Math.min(height, options.maxHeight || this.maxHeight)

在 fit() 函数中

fit() {
const {options, ctx} = this;
if (!options.display) {
  this.width = this.height = 0;
  return;
}
const labelOpts = options.labels;
const labelFont = toFont(labelOpts.font);
const fontSize = labelFont.size;
const titleHeight = this._computeTitleHeight();
const {boxWidth, itemHeight} = getBoxSize(labelOpts, fontSize);
let width, height;
ctx.font = labelFont.string;
if (this.isHorizontal()) {
  width = this.maxWidth;
  height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight);
} else {
  height = this.maxHeight;
  width = this._fitCols(titleHeight, fontSize, boxWidth, itemHeight);
}
this.width = Math.min(width, options.maxWidth || this.maxWidth);
this.height = Math.min(height, options.maxHeight || this.maxHeight) + 40;}

我把它改成了+40,如上所示。它对我来说很好,所以我想分享。


0
投票

如果您只想在您的应用中为某些图表应用图例下方的填充:

ChartJS >= 2.1.0

注意:确保将其添加到

plugins
中而不是
options.plugins
中。

Chart.plugins.register({
  id: 'paddingBelowLegends',
  beforeInit: function(chart, options) {
    chart.legend.afterFit = function() {
      this.height = this.height + 50;
    };
  }
});

// ----------------------------------
// disable the plugin only for charts
// where you DO NOT WANT the padding
// ----------------------------------

// for raw ChartJS use:
var chart = new Chart(ctx, {
  config: {
    plugins: {
      paddingBelowLegends: false
    }
  }
});

对于使用

react-chartjs-2
的 React 用户:

import { Line } from "react-chartjs-2";
import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend } from "chart.js";
  ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Title, Tooltip, Legend);
<Line
        data={{
          datasets: trendsData?.map((trend, idx) => ({
            type: "line",
            label: trend.domainName,
            data: trend.domainTrends.map(d => d.value),
            backgroundColor: getDomainColor(idx).backgroundColor,
            borderColor: getDomainColor(idx).color,
            pointRadius: 0,
            tension: 0.3
          })),
          labels: trendsData?.[0]?.domainTrends.map(d => d.date)
        }}
        options={{
          plugins: {
            legend: {
              display: true,
              align: "start",
              labels: {
                font: { size: 14 }
              }
            }
          }
        }}
        plugins={[
          {
            id: "increase-legend-spacing",
            beforeInit(chart) {
              // Get reference to the original fit function
              const originalFit = (chart.legend as any).fit;
              // Override the fit function
              (chart.legend as any).fit = function fit() {
                // Call original function and bind scope in order to use `this` correctly inside it
                originalFit.bind(chart.legend)();
                this.height += 20;
              };
            }
          }
        ]}
      />

0
投票

我知道这不是 OP 真正想要的,但至少对于较新的版本,以及我使用的版本 - 4.0.1 - 没有办法增加图例框和图表之间的边距,我已经找到了至少,所以这是一个明显的解决方法。所以为了避免这个问题:

我必须使用此选项配置更改图表下方的 leyend 框的位置:

options = {
    layout: {
        padding: 30
    },
    parsing: {
        key: 'nested.value'
    },
    plugins: {
        datalabels: {
            color: '#36A2EB'
        },
        tooltip: {
            enabled: true
        },
        legend: {
            position: 'bottom',
            align: 'center',
            labels: {
                padding: 20,
            }
        }
    }
};

注意:要在条形顶部添加值,我必须在数据集配置中添加具有以下功能的 npm 包 chartjs-plugin-datalabels:

datasets: [
    {
        label: "Ejercido",
        data: source.map( s => s.ejercidoTotal),
        datalabels: {
        anchor: 'end',
        clamp: true,//this makes one datalabel not visible if it crashed with other one
        display: 'auto',
        align: 'top',
        color: '#333333',
        formatter
        }
    },
    ...
]

最后的结果是:


0
投票

如果您使用

react-chartjs-2
库在 React 应用程序中显示图表。您可以使用以下解决方案:

const plugin = {
  beforeInit: function (chart) {
    // Get reference to the original fit function
    const originalFit = chart.legend.fit

    // Override the fit function
    chart.legend.fit = function fit() {
      // Bind scope in order to use `this` correctly inside it
      originalFit.bind(chart.legend)()
      this.height += 20 // Change the height
    }
  }
}

export const ReactChart2Example = (props) => {
  const { data = [] } = props;

  return (
    <div>
      <Chart plugins={[plugin]} type ="bar" data={data}/>
    </div>
  );
};

我们必须在 React js Chart 组件中单独传递

plugins
属性,而不是在
options
内部。

参考:https://github.com/chartjs/Chart.js/issues/10388#issuecomment-1217363379


-8
投票

您可以在选项下使用布局属性。这对我有帮助:

   layout: {
        padding: {
            left: 50,
            right: 130,
            top: 0,
            bottom: 0
        }
    }

© www.soinside.com 2019 - 2024. All rights reserved.