UNPKG

@nebula.js/sn-line-chart

Version:
362 lines (318 loc) 8.91 kB
# @nebula.js/sn-line-chart The line chart is a common, widely used visualization. It is often used to show trends over time. ## Requirements Requires `@nebula.js/stardust` version `1.7.0` or later. ## Installing If you use npm: `npm install @nebula.js/sn-line-chart`. You can also load through the script tag directly from [https://unpkg.com](https://unpkg.com/@nebula.js/sn-line-chart). ## Usage ```js import { embed } from '@nebula.js/stardust'; import line from '@nebula.js/sn-line-chart'; // 'app' is an enigma app model const nuked = embed(app, { types: [ { // register line chart name: 'line-chart', load: () => Promise.resolve(line), }, ], }); nuked.render({ element: document.querySelector('.lines'), type: 'line-chart', fields: ['Date.autoCalendar.YearMonth', '=Avg(Gold)', '=Avg(Bitcoin)'], // Overrides default properties properties: { title: 'Price of Gold and Bitcoin', dataPoint: { show: true, showLabels: true, }, gridLine: { auto: false, }, dimensionAxis: { show: 'all', dock: 'near', }, measureAxis: { spacing: 0.5, dock: 'near', show: 'all', logarithmic: true, }, }, }); ``` ## More examples ### One dimension, two measures, area styling ```js nuked.render({ element: document.querySelector('.lines'), type: 'line-chart', fields: ['Date.autoCalendar.YearMonth', '=Avg(Gold)', '=Avg(Bitcoin)'], // Overrides default properties properties: { lineType: 'area', }, }); ``` ### One dimension, two measures, vertical orientation ```js nuked.render({ element: document.querySelector('.lines'), type: 'line-chart', fields: ['Date.autoCalendar.Quarter', 'Date.autoCalendar.Year', '=Avg(Bitcoin)'], // Overrides default properties properties: { orientation: 'vertical', dimensionAxis: { continuousAuto: false, dock: 'near', }, dataPoint: { show: true, showLabels: true, }, preferContinuousAxis: false, }, }); ``` ### Two dimensions, one measure ```js nuked.render({ element: document.querySelector('.lines'), type: 'line-chart', // Two dimensions, one measure fields: ['Date.autoCalendar.Quarter', 'Date.autoCalendar.Year', '=Avg(Bitcoin)'], properties: { measureAxis: { dock: 'near', show: 'all', logarithmic: true, }, dataPoint: { show: true, showLabels: true, }, }, }); ``` ### One dimension, two measures, two reference lines ```js nuked.render({ element: document.querySelector('.lines'), type: 'line-chart', fields: ['Date.autoCalendar.YearMonth', '=Avg(Gold)', '=Avg(Bitcoin)'], // Overrides default properties properties: { refLine: { refLines: [ { label: '', paletteColor: { color: 'green', }, refLineExpr: { value: 52500, }, show: true, }, { label: '', paletteColor: { color: 'red', }, refLineExpr: { value: 3570, }, show: true, }, ], }, measureAxis: { dock: 'near', show: 'all', logarithmic: true, }, dataPoint: { show: true, }, }, }); }); ``` ## Line chart plugins A plugin can be passed into a line chart to add or modify its capability or visual appearance. A plugin needs to be defined before it can be rendered together with the chart. ```js // Step 1: define the plugin // Modifying the look of the minor axis title const minorAxisTitlePlugin = { info: { name: 'minor-axis-title-plugin', type: 'component-definition', }, fn: ({ keys, layout }) => { const componentDefinition = { type: 'data-title', // Provide the same name as the exisiting component to override it key: keys.COMPONENT.MINOR_AXIS_TITLE, style: { fontFamily: 'Tahoma, san-serif', fontSize: '15px', }, }; return componentDefinition; }, }; // Step 2: passing the plugin definition into the render function // Rendering a line chart with plugins nuked.render({ element: document.querySelector('#object'), type: 'sn-line-chart', plugins: [majorAxisTitlePlugin], fields: ['Date.autoCalendar.YearMonth', '=Avg(Gold)', '=Avg(Bitcoin)'], // eslint-disable-next-line no-undef properties: { title: 'History Price of Gold vesus Bitcoin (USD)', measureAxis: { show: 'all', logarithmic: true }, }, }); ``` The plugin definition is an object, with two properties `info` and `fn`. The `fn` returns a `picasso.js` component. To build this component, some important chart internals are passed into the argument object of `fn`. ```js // Structure of the argument object of fn const pluginArgs = { layout, keys: { SCALE: { MAIN: { MINOR, MAJOR, }, }, COMPONENT: { LINE, MAJOR_AXIS, MAJOR_AXIS_TIME_INNER, MAJOR_AXIS_TITLE, MINOR_AXIS, MINOR_AXIS_TITLE, }, COLLECTION: { MAIN, }, }, }; ``` With plugins, you can either add new components or modify existing components of the line chart. ### Add new components The new component can be a standard Picasso component or a custom Picasso component. Here we demo a custom component which add labels to the min/max positions of the line. ```js // Implement a custom min/max labels plugin, so that we can use it later // to show the min/max of Bitcoin price since 2018 const minMaxLabelsPluginImplementation = { info: { componentName: 'custom-labels-plugin', name: 'custom-labels-plugin', type: 'custom-component', }, fn: ({ keys }) => { const implementation = { require: ['chart', 'renderer'], render() { // We are only interested in data of Bitcoin after year 2018 const items = this.chart .component(keys.COMPONENT.LINE) .data.items.filter((item) => item.line.value === 1 && item.label >= '2018'); const scale = this.chart.scales(); const timeScale = scale[keys.SCALE.MAIN.MAJOR]; const lineScale = scale[keys.SCALE.MAIN.MINOR]; const { width, height } = this.rect; const min = Math.min(...items.map((item) => item.end.value)); const max = Math.max(...items.map((item) => item.end.value)); const labels = []; items.forEach((item) => { if (item.end.value === min) { labels.push({ type: 'text', text: `min: ${item.end.label}`, x: timeScale(item.major.value) * width, y: lineScale(item.end.value) * height + 15, anchor: 'middle', fontFamily: 'Tahoma, san-serif', fontSize: '15px', fill: 'darkred', }); } else if (item.end.value === max) { labels.push({ type: 'text', text: `max: ${item.end.label}`, x: timeScale(item.major.value) * width, y: lineScale(item.end.value) * height - 15, anchor: 'middle', fontFamily: 'Tahoma, san-serif', fontSize: '15px', fill: 'darkgreen', }); } }); return labels; }, }; return implementation; }, }; // Using the min/max labels plugin, defined above const minMaxLabelsPlugin = { info: { name: 'labels', type: 'component-definition', }, fn: ({ keys }) => { const componentDefinition = { // The type has to match with the componentName of the labels plugin definition above type: 'custom-labels-plugin', key: 'my-labels', }; return componentDefinition; }, }; ``` ### Modify existing components As an example, the appearance of the line can be modified by plugin. To overide an existing component, `fn` should returns a `picasso.js` component that has the same `key` as the existing component (`keys.COMPONENT.LINE` in this example) ```js // Modifying the look of the existing line component const linePlugin = { info: { name: 'line-plugin', type: 'component-definition', }, fn: ({ layout, keys }) => { const componentDefinition = { type: 'line', // Provide the same name as the exisiting line component to override it key: keys.COMPONENT.LINE, settings: { layers: { curve: 'monotone', line: { strokeWidth: 3 } }, }, }; return componentDefinition; }, }; ``` ### Plugins disclaimer - The plugins API is still experimental. - We can not guarantee our charts to be compatible with all different settings, especially when modifying existing components.