Легенда Chart.js заняла слишком много места

У меня были некоторые проблемы с легендой chart.js. Легенда с длинным текстом заняла слишком много места, что привело к уменьшению размера моей круговой диаграммы:

Еще один пример:

Если я получу больше легенд, диаграмма пончиков со временем станет все меньше и меньше.

Я пытался установить maxWidth, но безрезультатно.

var options = {
            layout: {
                padding: {
                  top: 5
                }
            },
            responsive: true,
            maintainAspectRatio: false,
            legend: {
                display: true,
                position: 'right',
                maxWidth: 100,
                onClick: null
            },
            animation: {
                animateScale: true,
                animateRotate: true
            },

        };

Есть идеи? Заранее спасибо!

Я попытался следовать этому [решению][3], чтобы создать легенду HTML:

<div class="box-body" style="height:350px;">
<div class="float-left">
<div class="float-left" style="width:70%">

<canvas id="brandChart" style="position: relative; height: 350px;"></canvas>
</div>
<div class="float-left" style="width:30%">

<div id="js-legend" class="chart-legend">
</div>

</div>
</div>

Это ограничило ширину легенды, но затем это привело к другой проблеме, которая заключается в том, что после того, как я свернул и расширил div, холст просто пропал, и у меня остался только легендарный div.

3 ответа

Решение

Во-первых, установите ширину и высоту холста, используя его собственные атрибуты (не используйте style атрибут), вот так:

<canvas id="brandChart" width="700" height="350"></canvas>

примечание: ширина должна быть в два раза больше высоты

Затем установите responsive собственность на false в опциях вашего графика, как таковые:

options: {
   responsive: false,
   ...
}

ᴅᴇᴍᴏ

var chart = new Chart(brandChart, {
   type: 'doughnut',
   data: {
      labels: ['Etronin Home Appliances Service & trading Pte Ltd', 'Giant'],
      datasets: [{
         data: [30, 70],
         backgroundColor: ['#2196f3', '#4caf50']
      }]
   },
   options: {
      responsive: false,
      legend: {
         display: true,
         position: 'right',
         onClick: null
      },
   }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="brandChart" width="700" height="350"></canvas>

Длинная легенда в настоящее время является проверкой известной проблемы https://github.com/chartjs/Chart.js/issues/3641

Может быть, они могут осветить это в следующих выпусках. На данный момент решение состоит в том, чтобы удалить родную легенду и нарисовать вашу собственную.

Я создал этот план в качестве примера для диаграммы контуров с пользовательской легендой https://embed.plnkr.co/5nuGS2KEV6hvESwGrOse/

Я столкнулся с аналогичной проблемой при использовании гистограммы с несколькими элементами в легенде, расположенными внизу, я установил responsive:true

 options: {
    responsive: true,
    legend: {
      display: true,
      position: "bottom",
      labels: {
        fontColor: "#3f5761"
      }
    },
    scales: {
      yAxes: [
        {
          ticks: {
            beginAtZero: true
          },
          scaleLabel: {
            display: true,
            labelString: "No. of tasks",
            fontSize: 10
          }
        }
      ]
    }
  }

и установите высоту холста, так как я хотел, чтобы ширина была гибкой. Теперь это выглядит лучше.

<canvas #taskCountsChart height="350"></canvas>

Нет варианта, который можно было бы определить, чтобы легко достичь того, что вы ищете. Открытый запрос функции существует для такой опции с 2016 года.

Вам нужно будет создать собственную легенду HTML, используяlegendCallback вместе с некоторыми CSS. В следующем коде предполагается, что многострочные метки будут определены как массивы внутриdata.labels. Он предназначен для использования в диаграммах с уникальнымdatasetи где каждая метка легенды представляет собой значение своих данных (если вам нужно решение для диаграммы с несколькими наборами данных, взгляните на этот ответ).

legendCallback: chart => {
  let html = '<ul>';
  chart.data.labels.forEach((l, i) => {
    const ds = chart.data.datasets[0];
    const bgColor = ds.backgroundColor[i];
    const border = ds.borderWidth + 'px solid ' + ds.borderColor[i];
    html += '<li>' +
      '<span style="width: 36px; height: 14px; background-color:' + bgColor + '; border:' + border + '" onclick="onLegendClicked(event, \'' + i + '\')">&nbsp;</span>' +
      '<span id="legend-label-' + i + '" onclick="onLegendClicked(event, \'' + i + '\')">' +
      (Array.isArray(l) ? l.join('<br/>') : l) + '</span>' +
      '</li>';
  });
  return html + '</ul>';
}

Чтобы это работало так же, как стандартные диаграммы Chart.js, функция onLegendClickedвызывается при щелчке мышью по метке легенды. Эта функция переключает скрытое состояние отдельных кусочков пончика и меняет стиль текста метки между обычным и зачеркнутым.

function onLegendClicked(e, i) {
  let hidden = !chart.getDatasetMeta(0).data[i].hidden;
  chart.getDatasetMeta(0).data[i].hidden = hidden;
  const legendLabelSpan = document.getElementById("legend-label-" + i);
  legendLabelSpan.style.textDecoration = hidden ? 'line-through' : '';
  chart.update();
};

Взгляните на исполняемый код ниже и посмотрите, как он работает в действии:

function onLegendClicked(e, i) {
  let hidden = !chart.getDatasetMeta(0).data[i].hidden;
  chart.getDatasetMeta(0).data[i].hidden = hidden;
  const legendLabelSpan = document.getElementById("legend-label-" + i);
  legendLabelSpan.style.textDecoration = hidden ? 'line-through' : '';
  chart.update();
};

const chart = new Chart('chart', {
  type: 'doughnut',
  data: {
    labels: [
      ['Label on', 'two lines'],     
      ['Legend label', 'spread over', 'three lines'],
       'A short label'
    ],
    datasets: [{
      data: [4, 5, 3],
      backgroundColor: ['rgba(255, 99, 132, 0.2)', 'rgba(255, 159, 64, 0.2)', 'rgba(54, 162, 235, 0.2)'],
      borderColor: ['rgb(255, 99, 132)', 'rgb(255, 159, 64)', 'rgb(54, 162, 235)'],
      borderWidth: 1
    }]
  },
  options: {
    legend: {
      display: false
    },
    tooltips: {
      callbacks: {
        title: (tooltipItems, data) => data.labels[tooltipItems[0].index],
        label: (tooltipItems, data) => 'Count: ' + data.datasets[0].data[tooltipItems.index]
      }
    },
    legendCallback: chart => {      
      let html = '<ul>';
      chart.data.labels.forEach((l, i) => {
        const ds = chart.data.datasets[0];
        const bgColor = ds.backgroundColor[i];
        const border = ds.borderWidth + 'px solid ' + ds.borderColor[i];
        html += '<li>' +
        '<span style="width: 36px; height: 14px; background-color:' + bgColor + '; border:' + border + '" onclick="onLegendClicked(event, \'' + i + '\')">&nbsp;</span>' +
        '<span id="legend-label-' + i + '" onclick="onLegendClicked(event, \'' + i + '\')">' +
        (Array.isArray(l) ? l.join('<br/>') : l) +'</span>' +
        '</li>';
      });
      return html + '</ul>';
    }
  }
});
document.getElementById("legend").innerHTML = chart.generateLegend();
#legend>ul {
  display: flex;
  justify-content: center;
}

#legend li {
  cursor: pointer;
  margin: 10px 10px;
  display: flex;
}

#legend li span {
  padding-left: 8px;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<div>
  <div id="legend"></div>
  <canvas id="chart" height="90"></canvas>
</div>

Этому сообщению 9 месяцев, но для тех, кто ищет решение, используйте следующее, и это сделает пирог / пончик больше в мобильном / адаптивном представлении

Chart.defaults.global.maintainAspectRatio = false;

Другие вопросы по тегам