Skip to content

Commit

Permalink
HTML Legend sample (#8804)
Browse files Browse the repository at this point in the history
  • Loading branch information
etimberg committed Apr 3, 2021
1 parent 35e8af7 commit 0192334
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/.vuepress/config.js
Expand Up @@ -167,6 +167,7 @@ module.exports = {
'legend/title',
'legend/point-style',
'legend/events',
'legend/html',
]
},
{
Expand Down
127 changes: 127 additions & 0 deletions docs/samples/legend/html.md
@@ -0,0 +1,127 @@
# HTML Legend

This example shows how to create a custom HTML legend using a plugin and connect it to the chart in lieu of the default on-canvas legend.

<div id="legend-container"></div>

```js chart-editor
// <block:plugin:0>
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 = () => {
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);
});
}
};
// </block:plugin>

// <block:data:1>
const NUM_DATA = 7;
const NUM_CFG = {count: NUM_DATA, min: 0, max: 100};
const data = {
labels: Utils.months({count: NUM_DATA}),
datasets: [
{
label: 'Dataset: 1',
data: Utils.numbers(NUM_CFG),
borderColor: Utils.CHART_COLORS.red,
backgroundColor: Utils.transparentize(Utils.CHART_COLORS.red, 0.5),
fill: false,
},
{
label: 'Dataset: 1',
data: Utils.numbers(NUM_CFG),
borderColor: Utils.CHART_COLORS.blue,
backgroundColor: Utils.transparentize(Utils.CHART_COLORS.blue, 0.5),
fill: false,
},
],
};
// </block:data>

// <block:setup:2>
const config = {
type: 'line',
data: data,
options: {
plugins: {
htmlLegend: {
// ID of the container to put the legend in
containerID: 'legend-container',
},
legend: {
display: false,
}
}
},
plugins: [htmlLegendPlugin],
};
// </block:setup>

module.exports = {
actions: [],
config: config,
};
```

0 comments on commit 0192334

Please sign in to comment.