如何在chart.js中添加额外的图例项目?

时间:2020-08-25 13:29:42

标签: javascript chart.js

我有一个带有单个数据集的图表。这是条形图。我想将一些条形为黄色,将某些条形为红色。我可以使用数据集上的函数执行此操作。问题在于,图例仅显示整个数据集的一项。它变成黄色。我需要在图例中为红色项添加另一个项。

我尝试添加第二个数据集,但随后显示为两个条形图。我还没有尝试过堆积条形图。

如何为图例添加另一个元素?

var data = [
  { Name: 'John'    , FeesPaid: 100 , MemberType: 'NonMember' },
  { Name: 'Mary'    , FeesPaid:  87 , MemberType: 'Member'    },
  { Name: 'Charles' , FeesPaid: 108 , MemberType: 'Member'    },
  { Name: 'Fern'    , FeesPaid:  91 , MemberType: 'Member'    },
  { Name: 'Robert'  , FeesPaid: 100 , MemberType: 'NonMember' },
  { Name: 'Andrea'  , FeesPaid: 114 , MemberType: 'Member'    },
]

var labels = data.map((item, idx) => {
  return item.Name;
});

var values = data.map((item, idx) => {
  return item.FeesPaid;
});

var getColor = function(record) {
  var r = data[record.dataIndex];
  if (r.MemberType == "NonMember") {
    return '#f5be0b';
  } else {
    return 'rgb(255, 99, 132)';
  }
}

var ctx = document.getElementById('canvas').getContext('2d');
var chart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: labels,
    datasets: [{
      label: 'Non-Member',
      backgroundColor: getColor,
      borderColor: getColor,
      data: values
    }]
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas"></canvas>

这是codepen上的一面镜子:https://codepen.io/dagostinelli/pen/BaKWpJR

1 个答案:

答案 0 :(得分:0)

这是使用legendCallback的幼稚方法。

如果需要多个图例项,则开箱即用,将需要多个数据集。通常,每个数据集都有自己的标签。

const ctx = document.getElementById('canvas').getContext('2d');
const data = [
  { Name: 'John'    , FeesPaid: 100 , MemberType: 'NonMember' },
  { Name: 'Mary'    , FeesPaid:  87 , MemberType: 'Member'    },
  { Name: 'Charles' , FeesPaid: 108 , MemberType: 'Member'    },
  { Name: 'Fern'    , FeesPaid:  91 , MemberType: 'Member'    },
  { Name: 'Robert'  , FeesPaid: 100 , MemberType: 'NonMember' },
  { Name: 'Andrea'  , FeesPaid: 114 , MemberType: 'Member'    },
]

const fields = [
  { label: 'Member'    , color: 'rgb(255, 99, 132)' , active: true },
  { label: 'NonMember' , color: '#f5be0b'           , active: true }
];

const Colors = fields.reduce((obj, field) => ({ ...obj, [field.label]: field.color }), {});

const labels = data.map(item => item.Name);
const values = data.map(item => item.FeesPaid);

const getColor = record => {
  const r = data.find(d => d.Name === record.chart.data.labels[record.dataIndex]);
  return r ? Colors[r.MemberType] : Colors.NonMember;
};

const customLegendRenderer = (chart) => {
  return `
    <ul class="custom-legend ${chart.id}-legend">
      ${fields.map(field => `
        <li data-field="${field.label}" data-active="${field.active}">
          <span style="background-color:${field.color}"></span>
          ${field.label}
        </li>
      `).join('')}
    </ul>
  `;
};

const chart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: labels,
    datasets: [{
      backgroundColor: getColor,
      borderColor: getColor,
      data: values
    }]
  },
  options: {
    legend: false,
    legendCallback: customLegendRenderer
  }
});

const handleClick = (e) => {
  const labels = chart.data.labels;
  const dataset = chart.data.datasets[0];
  const item = e.target.closest('li');
  if (item === null) return;
  const selected = fields.find(field => field.label === item.dataset.field);
  selected.active = !selected.active;
  const activeFields = fields.filter(field => field.active).map(field => field.label);
  while (dataset.data.length && labels.length) {
    dataset.data.pop();
    labels.pop();
  }
  const filteredData = data.filter(record => activeFields.includes(record.MemberType));
  filteredData.forEach(item => {
    dataset.data.push(item.FeesPaid);
    labels.push(item.Name);
  });
  chart.update();
  customLegend.innerHTML = chart.generateLegend();
};

const customLegend = document.querySelector('#chartjs-legend');
customLegend.innerHTML = chart.generateLegend();
customLegend.addEventListener('click', handleClick);
.custom-legend {
  display: flex;
  flex-direction: row;
  justify-content: space-evenly;
  list-style-type: none;
}

.custom-legend li[data-active="false"] {
  color: #777;
  text-decoration: line-through;
}

.custom-legend li span {
  display: inline-block;
  width: 1em;
  height: 1em;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas"></canvas>
<div id="chartjs-legend" class="noselect"></div>

相关问题