为ChartJS图例标签显示带点的线

4urapxun  于 2023-03-29  发布在  Chart.js
关注(0)|答案(1)|浏览(190)

我试图创建一个ChartJS图例,它为每个标签显示一条中心有一个点的线,这样你就可以通过特定样式的线和点的类型来识别图例中的数据集。
到目前为止,我已经能够使用数据集中的单个点作为图例标签,或者通过使用自定义的generateLabels函数显示一条没有额外点的样式线。
小提琴:https://jsfiddle.net/gpkdvjb5/33/
我使用的ChartJS版本是v3.9.1。

const NUM_DATA = 7;
const NUM_CFG = {count: NUM_DATA, min: 0, max: 100};
const data = {
  labels: ['a','b','c','d','e','f','g'],
  datasets: [
    {
      label: 'Dataset: 1',
      data: [100, 150, 150, 100, 150, 150, 100],
      pointRadius: 10,
      pointStyle: 'rect',
      borderDash: [5,18],
      borderColor: 'blue',
      backgroundColor: 'red',
      fill: false,
    },
    {
      label: 'Dataset: 1',
      data: [200, 170, 170, 200, 170, 170, 200],
      borderDash: [5,5,5],
      pointRadius: 10,
      borderColor: 'blue',
      pointStyle: 'crossRot',
      backgroundColor: 'blue',
      fill: false,
    },
  ],
};

const config = {
  type: 'line',
  data: data,
  options: {
    plugins: {
      legend: {
        labels: {
            usePointStyle: true
        }
      }
    }
  },
};

config.options.plugins.legend.labels.pointStyleWidth = 60;
        
// Using line styling for labels instead of points
config.options.plugins.legend.labels.generateLabels = (chart) => {
    const datasets = chart.data.datasets;
    const options = chart.options.legend || {};
    return chart._getSortedDatasetMetas().map((meta) => {
        const style = meta.controller.getStyle();

        return {
            text: datasets[meta.index].label,
            fillStyle: style.backgroundColor,
            hidden: !meta.visible,
            lineCap: style.borderCapStyle,
            lineDash: style.borderDash,
            lineDashOffset: style.borderDashOffset,
            lineJoin: style.borderJoinStyle,
            lineWidth: style.borderWidth,
            strokeStyle: style.borderColor,
            pointStyle: 'line',
            rotation: style.rotation,
            // Below is extra data used for toggling the datasets
            datasetIndex: meta.index
        };
    });
};

let canvas = document.getElementById('test-canvas');
let chart = new Chart(
    canvas,
    config
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.js"></script>
<canvas id="test-canvas"></canvas>
kulphzqa

kulphzqa1#

您可以使用generateLabels函数返回的标签的pointStyleHTMLCanvasElement选项创建自定义图例标签。
该技术在代码中的简化应用如下:

const NUM_DATA = 7;
const NUM_CFG = {count: NUM_DATA, min: 0, max: 100};
const data = {
    labels: ['a','b','c','d','e','f','g'],
    datasets: [
        {
            label: 'Dataset: red',
            data: [100, 150, 150, 100, 150, 150, 100],
            pointRadius: 10,
            pointStyle: 'rect',
            borderDash: [5,18],
            borderColor: 'blue',
            backgroundColor: 'red',
            fill: false,
        },
        {
            label: 'Dataset: blue',
            data: [200, 170, 170, 200, 170, 170, 200],
            borderDash: [5,5,5],
            pointRadius: 10,
            borderColor: 'blue',
            pointStyle: 'crossRot',
            backgroundColor: 'blue',
            fill: false,
        },
    ],
};

const config = {
    type: 'line',
    data: data,
    options: {
        plugins: {
            legend: {
                labels: {
                    usePointStyle: true
                }
            }
        }
    },
};

config.options.plugins.legend.labels.pointStyleWidth = 60;

// Using line styling for labels instead of points
config.options.plugins.legend.labels.generateLabels = (chart) => {
    const datasets = chart.data.datasets;
    const options = chart.options.legend || {};
    return chart._getSortedDatasetMetas().map((meta) => {
        const style = meta.controller.getStyle(),
            dataSet = datasets[meta.index];
        return {
            text: dataSet.label,
            hidden: !meta.visible,
            pointStyle: (function(){
                const canvas = document.createElement('canvas');
                canvas.setAttribute('width', "50");
                canvas.setAttribute('height', "20");
                const context = canvas.getContext("2d");

                context.lineWidth = style.borderWidth;
                context.lineCap = style.borderCapStyle;
                context.lineJoin = style.borderJoinStyle;
                context.setLineDash(style.borderDash);
                context.dashOffset = style.lineDashOffset;
                context.strokeStyle = style.borderColor;

                // draw the line
                context.beginPath();
                context.moveTo(1, 10);
                context.lineTo(50, 10);
                context.stroke();
                context.fillStyle = style.backgroundColor;

                context.setLineDash([]);
                context.lineWidth = 1;
                // draw the standard symbol
                Chart.helpers.drawPoint(context, {
                    pointStyle: dataSet.pointStyle,
                    borderWidth: style.borderWidth,
                    radius: Math.min(dataSet.pointRadius, 10),
                }, 25, 10);

                // or draw a circle
                // context.beginPath();
                // //context.beginPath();
                // context.arc(25, 10, 4, 0, 2 * Math.PI);
                // context.fill();

                return canvas;
            })(),
            //rotation: style.rotation, rotation ignored

            datasetIndex: meta.index
        };
    });
};

let canvas = document.getElementById('test-canvas');
let chart = new Chart(
    canvas,
    config
);
<canvas id="test-canvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js" integrity="sha512-ElRFoEQdI5Ht6kZvyzXhYG9NqjtkmlkfYk0wr6wHxU9JEHakS7UJZNeml5ALk+8IKlU6jDgMabC3vkumRokgJA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

相关问题