diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index deded3635..c236f83be 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -126,6 +126,7 @@ module.exports = { 'label/callout', 'label/canvas', 'label/image', + 'label/innerChart', 'label/lowerUpper', ] }, diff --git a/docs/samples/label/innerChart.md b/docs/samples/label/innerChart.md new file mode 100644 index 000000000..2e9c26e36 --- /dev/null +++ b/docs/samples/label/innerChart.md @@ -0,0 +1,158 @@ +# Inner chart + +```js chart-editor +// +const DATA_COUNT = 12; +const MIN = 0; +const MAX = 100; + +const innerChart = Utils.getChart(); +const innerDataset = innerChart.data.datasets[0]; + +const numberCfg = {count: DATA_COUNT, min: MIN, max: MAX}; + +const data = { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + datasets: [{ + data: Utils.numbers(numberCfg), + borderColor: innerDataset.backgroundColor[0], + backgroundColor: 'transparent' + }, { + data: Utils.numbers(numberCfg), + borderColor: innerDataset.backgroundColor[1], + backgroundColor: 'transparent', + hidden: true + }, { + data: Utils.numbers(numberCfg), + borderColor: innerDataset.backgroundColor[2], + backgroundColor: 'transparent', + hidden: true + }] +}; +// + +// +const annotation1 = { + type: 'label', + content: innerChart.canvas, + xValue: 1, + yValue: 135, + enter: (ctx) => setCursor(ctx, 'pointer'), + leave: (ctx) => setCursor(ctx, 'default'), + click: clickOnInnerChart +}; +// + +// +const annotation2 = { + type: 'label', + content: (ctx) => [innerChart.data.labels[getVisibleDatasetIndex(ctx)], + 'items trend'], + callout: { + enabled: true, + position: 'bottom', + margin: 0 + }, + font: { + size: 16 + }, + backgroundColor: 'white', + borderWidth: 1, + xAdjust: -60, + xValue: (ctx) => point(ctx).x, + yAdjust: -60, + yValue: (ctx) => point(ctx).y +}; +// + +// +const annotation3 = { + type: 'label', + content: ['Click on a slice of the pie chart', 'to see the data in the main chart'], + color: 'rgba(0, 0, 0, 0.5)', + xValue: 3.2, + yValue: 150, +}; +// + +/* */ +const config = { + type: 'line', + data, + options: { + scales: { + y: { + beginAtZero: true, + min: 0, + max: 160 + } + }, + plugins: { + annotation: { + annotations: { + annotation1, + annotation2, + annotation3 + } + } + } + } +}; +/* */ + +// +function clickOnInnerChart(ctx, event) { + event.x = event.x - ctx.element.x; + event.y = event.y - ctx.element.y; + const elements = innerChart.getElementsAtEventForMode(event, 'point', {}, true); + if (elements.length) { + const first = elements[0]; + ctx.chart.setDatasetVisibility(getVisibleDatasetIndex(ctx), false); + ctx.chart.show(first.index); + } +} + +function getVisibleDatasetIndex(ctx) { + const chart = ctx.chart; + for (let i = 0; i < chart.data.datasets.length; i++) { + if (chart.isDatasetVisible(i)) { + return i; + } + } + return 0; +} + +function point(ctx) { + const dataset = ctx.chart.data.datasets[getVisibleDatasetIndex(ctx)]; + const values = dataset.data.filter((value, i) => i > dataset.data.length - 4); + const y = Math.max(...values); + const x = dataset.data.lastIndexOf(y); + return {x, y}; +} + +function setCursor(ctx, type) { + ctx.chart.canvas.style.cursor = type; +} +// + +const actions = [ + { + name: 'Randomize', + handler: function(chart) { + chart.data.datasets.forEach(function(dataset, i) { + dataset.data = dataset.data.map(() => Utils.rand(MIN, MAX)); + }); + chart.update(); + innerChart.data.datasets.forEach(function(dataset, i) { + dataset.data = dataset.data.map(() => Utils.rand(MIN, MAX)); + }); + innerChart.update(); + } + } +]; + +module.exports = { + actions: actions, + config: config +}; +``` diff --git a/docs/scripts/utils.js b/docs/scripts/utils.js index a2f5d0eb9..0778fac74 100644 --- a/docs/scripts/utils.js +++ b/docs/scripts/utils.js @@ -1,7 +1,8 @@ +import {Chart} from 'chart.js'; import {valueOrDefault} from 'chart.js/helpers'; // Adapted from http://indiegamr.com/generate-repeatable-random-numbers-in-js/ -var _seed = Date.now(); +let _seed = Date.now(); export function srand(seed) { _seed = seed; @@ -50,6 +51,21 @@ export function getImage() { return img; } +let pieChart = null; + +export function getChart() { + if (pieChart) { + return pieChart; + } + const canvas = document.createElement('canvas'); + canvas.width = 100; + canvas.height = 100; + canvas.style.visibility = 'hidden'; + document.body.appendChild(canvas); + pieChart = createChart(canvas); + return pieChart; +} + export function getSpiral() { const canvas = document.createElement('canvas'); canvas.width = 150; @@ -88,3 +104,27 @@ export function getHouse() { ctx.stroke(); return canvas; } + +function createChart(canvas) { + return new Chart(canvas, { + type: 'pie', + data: { + labels: ['Bought', 'Sold', 'Rented'], + datasets: [{ + data: [42, 33, 25], + backgroundColor: ['#3366cc', '#dc3912', '#ff9900'] + }] + }, + options: { + responsive: false, + animation: false, + plugins: { + autocolors: false, + version: false, + legend: false, + title: false, + subtitle: false + } + } + }); +}