【问题标题】:Align doughnut/pie charts vertically in the container在容器中垂直对齐甜甜圈/饼图
【发布时间】:2022-01-30 22:50:48
【问题描述】:

我有三个并排的甜甜圈图,如下所示:

问题是,图表之间的项目数不同,导致图例高度不同,进而导致图表不对齐。是否可以将图表与容器顶部对齐?

【问题讨论】:

    标签: chart.js chart.js3


    【解决方案1】:

    您需要为此使用自定义插件来制作 html 图例:

    const getOrCreateLegendList = (chart, id) => {
      const legendContainer = document.getElementById(id);
      let listContainer = legendContainer.querySelector('ul');
    
      if (!listContainer) {
        listContainer = document.createElement('ul');
        listContainer.style.display = 'flex';
        listContainer.style.flexDirection = 'row';
        listContainer.style.margin = 0;
        listContainer.style.padding = 0;
    
        legendContainer.appendChild(listContainer);
      }
    
      return listContainer;
    };
    
    const htmlLegendPlugin = {
      id: 'htmlLegend',
      afterUpdate(chart, args, options) {
        const ul = getOrCreateLegendList(chart, options.containerID);
    
        // Remove old legend items
        while (ul.firstChild) {
          ul.firstChild.remove();
        }
    
        // Reuse the built-in legendItems generator
        const items = chart.options.plugins.legend.labels.generateLabels(chart);
    
        items.forEach(item => {
          const li = document.createElement('li');
          li.style.alignItems = 'center';
          li.style.cursor = 'pointer';
          li.style.display = 'flex';
          li.style.flexDirection = 'row';
          li.style.marginLeft = '10px';
    
          li.onclick = () => {
            const {
              type
            } = chart.config;
            if (type === 'pie' || type === 'doughnut') {
              // Pie and doughnut charts only have a single dataset and visibility is per item
              chart.toggleDataVisibility(item.index);
            } else {
              chart.setDatasetVisibility(item.datasetIndex, !chart.isDatasetVisible(item.datasetIndex));
            }
            chart.update();
          };
    
          // Color box
          const boxSpan = document.createElement('span');
          boxSpan.style.background = item.fillStyle;
          boxSpan.style.borderColor = item.strokeStyle;
          boxSpan.style.borderWidth = item.lineWidth + 'px';
          boxSpan.style.display = 'inline-block';
          boxSpan.style.height = '20px';
          boxSpan.style.marginRight = '10px';
          boxSpan.style.width = '20px';
    
          // Text
          const textContainer = document.createElement('p');
          textContainer.style.color = item.fontColor;
          textContainer.style.margin = 0;
          textContainer.style.padding = 0;
          textContainer.style.textDecoration = item.hidden ? 'line-through' : '';
    
          const text = document.createTextNode(item.text);
          textContainer.appendChild(text);
    
          li.appendChild(boxSpan);
          li.appendChild(textContainer);
          ul.appendChild(li);
        });
      }
    };
    
    const options = {
      type: 'line',
      data: {
        labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            borderColor: 'pink',
            backgroundColor: 'pink'
          },
          {
            label: '# of Points',
            data: [7, 11, 5, 8, 3, 7],
            borderColor: 'orange',
            backgroundColor: 'orange'
          }
        ]
      },
      options: {
        plugins: {
          legend: {
            display: false,
          },
          htmlLegend: {
            // ID of the container to put the legend in
            containerID: 'legend-container',
          }
        }
      },
      plugins: [htmlLegendPlugin],
    }
    
    const ctx = document.getElementById('chartJSContainer').getContext('2d');
    new Chart(ctx, options);
    <body>
      <div id="legend-container"></div>
      <canvas id="chartJSContainer" width="600" height="400"></canvas>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
    </body>

    【讨论】:

    • 哦,我希望有一种内置的方法我错过了,但这可以解决问题!
    • 不,没有构建方式 afaik