From: Evert Timberg Date: Sat, 3 Apr 2021 20:10:39 +0000 (-0400) Subject: HTML Legend sample (#8804) X-Git-Tag: v3.1.0~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=019233457fe7023884372aa0047f97519905d174;p=thirdparty%2FChart.js.git HTML Legend sample (#8804) --- diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 701b23a8e..436e3ab19 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -167,6 +167,7 @@ module.exports = { 'legend/title', 'legend/point-style', 'legend/events', + 'legend/html', ] }, { diff --git a/docs/samples/legend/html.md b/docs/samples/legend/html.md new file mode 100644 index 000000000..ab0add511 --- /dev/null +++ b/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. + +
+ +```js chart-editor +// +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); + }); + } +}; +// + +// +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, + }, + ], +}; +// + +// +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], +}; +// + +module.exports = { + actions: [], + config: config, +}; +```