1.3.1 • Published 6 years ago

interpolated-charts v1.3.1

Weekly downloads
1
License
ISC
Repository
github
Last release
6 years ago

Interpolated Charts

Configurable d3 v4 charts with interpolation and missing data range. Inspired by Britecharts

Angular component here

npm version

Live demo

default-interpolated-chart

Description

  • Configurable line chart with tooltip and markers
  • Gasps between data points (missing data range)
  • Compute and display interpolated values between data points

Iterpolation values are calculated on svg path element using the binary search method. It means that after changing chart curve type (d3.curveBasis, d3.curveCatmullRom, ...) computed values can change. Do not rely on this data if you need high accuracy.

Installation

  1. Install with npm
npm install interpolated-charts --save
  1. Import JS dependencies
import * as d3 from 'd3';
import { line, stackBar, chartEvents, verticalDivider, markers, tooltip } from 'interpolated-charts';
  1. Import CSS
@import 'interpolated-charts/src/index.css'

Usage

Package include line chart and three plugins: vertical divider, markers highlight, tooltip information. Line chart dispatch mouse events (chartMouseEnter, chartMouseLeave, chartMouseMove, chartMouseClick), defined in chartEvents. Default configuration for chart with plugins:

const verticalDividerPlugin = verticalDivider();
const markersPlugin = markers();
const tooltipPlugin = tooltip();

const lineChart = line()
  // subscribe plugins to chart events
  .on(chartEvents.chartMouseEnter, () => {
    verticalDividerPlugin.show();
  })
  .on(chartEvents.chartMouseLeave, () => {
    verticalDividerPlugin.remove();
    markersPlugin.remove();
    tooltipPlugin.remove();
  })
  .on(chartEvents.chartMouseMove, (options) => {
    verticalDividerPlugin.update(options);
    markersPlugin.show(options);
    tooltipPlugin.show(options);
  });

// create chart with data
const chartContainer = d3.select('.default-chart');
chartContainer.datum(lineChartData).call(lineChart);

// bind plugins to chart
const metadataContainer = d3.select('.default-chart .metadata-container');
metadataContainer.datum([]).call(verticalDividerPlugin);
metadataContainer.datum([]).call(markersPlugin);
metadataContainer.datum([]).call(tooltipPlugin);

Chart data example:

const lineChartData = [
  // each object represent chart line dataset
  {
    'name': 'Minsk',
    // optional color
    'color': 'darkblue',
    'data': [
      { 'date': new Date('2015-01-01T00:00:00'), 'value': 20 },
      { 'date': new Date('2015-01-02T00:00:00'), 'value': 16 }
    ]
  }
]

Default chart is first example on demo page.

Source code for examples - /demo.

Package include internal @types for Typescript.

Documentation

Line Chart

Usage

// create chart with custom config
const lineChart = line({ width: 900 });
// set property on existing chart
lineChart.curve(d3.curveCatmullRom);
// get d3 selection for chart container
const chartContainer = d3.select('.default-chart');
const lineChartData = [/* PathDataSet[] */];
// bind selection with data and call chart creation
chartContainer.datum(lineChartData).call(lineChart);

Chart data format

interface PathDataSet {
  name: string;
  color?: string;
  data: { date: Date, value: number }[];
}

Events

chartEvents.chartMouseEnter - mouse entered chart boundary. Arguments - mouse coordinates x, y relative to chart;

chartEvents.chartMouseLeave - mouse leaved chart boundary. Arguments - mouse coordinates x, y relative to chart;

chartEvents.chartMouseMove - mouse moved inside chart boundary. Event treshhold (mouseMoveTimeTreshold, ms) - min time between events. Arguments - { x: number, y: number, selectedDate: Date, data: PointData[] }. data - array of closest chart points data based on mouse current position:

interface PointData {
  // concrete values from PathDataSet and their coordinates on graph
  date: Date;
  value: number;
  x: number;
  y: number;
  // interpolated values, closest to mouse position
  interpolatedX: number;
  interpolatedY: number;
  interpolatedDate: Date;
  interpolatedValue: number;

  name: string;
  color: string;
}

chartEvents.chartMouseClick - mouse click inside chart boundary. Arguments - { x: number, y: number, selectedDate: Date, data: PointData[] }.

CSS

Chart grid lines css classes:

.line-chart .horizontal-grid-line, .line-chart .vertical-grid-line

Options

NameDescriptionTypeDefault
widthChart total widthNumber700
heightChart total heightNumber500
marginChart graph margin to outer bounds{ top: number, right: number, bottom: number, left: number }{ top: 20, right: 30, bottom: 40, left: 40 }
maxTimeRangeDifferenceToDrawMax time in milliseconds to treat dataset points without breakingNumber1000 60 60 24 1.5 (1.5 days)
xAxisTimeFormatDate tick format for chart X Axisd3.tickFormatundefined
yAxisValueFormatValue tick format for chart Y Axisd3.tickFormatundefined
curveCurve type for line interpolation. Important: value interpolation compute on chart resulted line and depend on this config valued3.curved3.curveBasis
chartHeightChart graph actual heigth getter. Total height - (margin.top + margin.bottom)Number
chartWidthChart graph actual width getter. Total width - (margin.left + margin.rightNumber
interpolationMaxIterationCountInterpolation cycle count. Computing will stop after N cycle or when Δx < accuracy Important: high value can slow preformanceNumber50
interpolationAccuracyInterpolation Δx accuracy for searching y value on svg path. Computing will stop after N cycle or when Δx < accuracyNumber0.005
mouseMoveTimeTresholdMinimum time in milliseconds between chartMouseMove eventsNumber20
xAxisDateFromChart X Axis start dateDateundefined
xAxisDateToChart X Axis end dateDateundefined

Bar chart

Usage

// create bar chart
const barChart = bar();

const barChartContainer = d3.select('.bar-bar');
const barChartData = [/* PathDataSet[] */];
// bind selection with data and call chart creation
barChartContainer.datum(barChartData).call(barChart);

Chart data format

Array of

interface StackBarData {
  name: string;
  backgroundColor?: string;
  data: {
    date: Date,
    color?: string,
    value: any
  }[];
}

Events

chartEvents.chartMouseEnter - mouse entered chart boundary. Arguments - mouse coordinates x, y relative to chart;

chartEvents.chartMouseLeave - mouse leaved chart boundary. Arguments - mouse coordinates x, y relative to chart;

chartEvents.chartMouseMove - mouse moved inside chart boundary. Event treshhold (mouseMoveTimeTreshold, ms) - min time between events. Arguments - { x: number, y: number, selectedDate: Date, data: MouseEventBarChartData[] }. data - array of closest chart points data based on mouse current position:

chartEvents.chartMouseClick - mouse click inside chart boundary. Arguments - { x: number, y: number, selectedDate: Date, data: MouseEventBarChartData[] }.

Options

NameDescriptionTypeDefault
widthChart total widthNumber700
heightChart total heightNumber120
marginChart graph margin to outer bounds{ top: number, right: number,
setStackWidthFunction to compute stack widthFunction(chartWidth, numberOfBars) => chartWidth / numberOfBars - 20
maxTimeRangeDifferenceToDrawMax time in milliseconds to treat dataset points without breakingNumber1000 60 60 24 1.5 (1.5 days)
stackTimeDiapasonTime diapason for one stackNumber1000 60 60 * 24
xAxisTimeFormatDate tick format for chart X Axisd3.tickFormatundefined
yAxisValueFormatValue tick format for chart Y Axisd3.tickFormatundefined
xAxisDateFromChart X Axis start dateDateundefined
xAxisDateToChart X Axis end dateDateundefined
yAxisValueFromChart Y Axis start valueNumberundefined
yAxisValueToChart Y Axis end valueNumberundefined

Stack bar

Usage

// create stack bar
const stackBarChart = stackBar();

const stackBarContainer = d3.select('.stack-bar');
const stackBarData = [/* StackBarData[] */];
// bind selection with data and call chart creation
stackBarContainer.datum(stackBarData).call(stackBarChart);

Chart data format

Array of

interface PathDataSet {
  name: string;
  color?: string;
  data: { date: Date, value: number }[];
}

Events

chartEvents.chartMouseEnter - mouse entered chart boundary. Arguments - mouse coordinates x, y relative to chart;

chartEvents.chartMouseLeave - mouse leaved chart boundary. Arguments - mouse coordinates x, y relative to chart;

chartEvents.chartMouseMove - mouse moved inside chart boundary. Event treshhold (mouseMoveTimeTreshold, ms) - min time between events. Arguments - { x: number, y: number, selectedDate: Date, diapasonStart: Date, diapasonEnd: Date, data: MouseEventBarChartData[] }. data - array of closest chart points data based on mouse current position:

chartEvents.chartMouseClick - mouse click inside chart boundary. Arguments - { x: number, y: number, selectedDate: Date, data: StackBarEventData[] }.

Options

NameDescriptionTypeDefault
widthChart total widthNumber700
heightChart total heightNumber120
marginChart graph margin to outer bounds{ top: number, right: number,
marginBetweenStacksVertical margin between multiple stack barsNumber0
backgroundColorChart background colorString'#CCCCCC'
maxTimeRangeDifferenceToDrawMax time in milliseconds to treat dataset points without breakingNumber1000 60 60 24 1.5 (1.5 days)
mouseMoveTimeTresholdMinimum time in milliseconds between chartMouseMove eventsNumber20
xAxisTimeFormatDate tick format for chart X Axisd3.tickFormatundefined
xAxisDateFromChart X Axis start dateDateundefined
xAxisDateToChart X Axis end dateDateundefined

Plugins

Vertical divider

Display vertical line on chart.

Usage
const lineChart = line({ height: 1000 });
// create plugin
const verticalDividerPlugin = verticalDivider();
// set divider height if chart height not default
verticalDividerPlugin
  .height(lineChart.chartHeight());
// subscribe plugin to chart events
lineChart
  .on(chartEvents.chartMouseEnter, (x, y) => verticalDividerPlugin.show())
  .on(chartEvents.chartMouseLeave, (x, y) => verticalDividerPlugin.remove())
  .on(chartEvents.chartMouseMove, (options) => verticalDividerPlugin.update(options));
// create line chart
d3.select('.interpolated-chart').datum([/* chart data */]).call(lineChart);
// select metadata container inside chart
const metadataContainer = d3.select('.interpolated-chart .metadata-container');
// call plugin creation
metadataContainer.datum([]).call(verticalDividerPlugin);
CSS

Divider line css class:

.line-chart .divider

Options
NameDescriptionTypeDefault
heightDivider line heightNumber440
Methods
NameDescriptionArguments
removeHide dividerNone
showShow dividerNone
updateSet divider position{ x: number }

Markers

Usage
const lineChart = line({ height: 1000 });
// create plugin with options
const markersPlugin = markers()
  .fill(data => {
    return data.interpolatedValue > 10 ? data.color : 'white'
  });
// set options
markersPlugin
  .radius(data => {
    return data.interpolatedValue > 10 ? 10 : 5
  })
// subscribe plugin to chart events
lineChart
  .on(chartEvents.chartMouseEnter, (x, y) => markersPlugin.show())
  .on(chartEvents.chartMouseLeave, (x, y) => markersPlugin.remove())
  .on(chartEvents.chartMouseMove, (options) => markersPlugin.update(options));
// create line chart
d3.select('.interpolated-chart').datum([/* chart data */]).call(lineChart);
// select metadata container inside chart
const metadataContainer = d3.select('.interpolated-chart .metadata-container');
// call plugin creation
metadataContainer.datum([]).call(markersPlugin);
Options
NameDescriptionTypeDefault
cxMarker X position calculatorFunctiondata => data.interpolatedXdata.x
cyMarker Y position calculatorFunctiondata => data.interpolatedYdata.y
radiusMarker radius calculatorFunctiondata => 5
fillMarker fill color calculatorFunctiondata => 'white'
strokeMarker stroke color calculatorFunctiondata => data.color'red'
strokeWidthMarker stroke width calculatorFunctiondata => 2
sortMarker sorting function. First value will be displayed on top of othersFunction(a, b) => 0
Methods
NameDescriptionArguments
removeHide markersNone
showShow markers{ data: ChartLinePointData[] }

Tooltip

Tooltip - html foreignObject in svg chart.

Usage
const lineChart = line({ height: 1000 });
// create plugin with options
const verticalDividerPlugin = verticalDivider({ chartHeight: lineChart.chartheight() });
// set options
tooltipPlugin
  .chartWidth(lineChart.chartWidth())
  .valueFormatter(({ interpolatedValue }) => `${interpolatedValue.toFixed(1)}°C`);
// subscribe plugin to chart events
lineChart
  .on(chartEvents.chartMouseEnter, (x, y) => tooltipPlugin.show())
  .on(chartEvents.chartMouseLeave, (x, y) => tooltipPlugin.remove())
  .on(chartEvents.chartMouseMove, (options) => tooltipPlugin.update(options));
// create line chart
d3.select('.interpolated-chart').datum([/* chart data */]).call(lineChart);
// select metadata container inside chart
const metadataContainer = d3.select('.interpolated-chart .metadata-container');
// call plugin creation
metadataContainer.datum([]).call(tooltipPlugin);
CSS

.line-chart .tooltip

.line-chart .tooltip rect

.line-chart .tooltip .tooltip-container

.line-chart .tooltip .tooltip-header

.line-chart .tooltip .tooltip-header p

.line-chart .tooltip .circle

.line-chart .tooltip .topic

.line-chart .tooltip .topic-name

.line-chart .tooltip .topic-value

Options
NameDescriptionTypeDefault
chartHeightChart height (used to compute tooltip boundaries)Number440
chartWidthChart width (used to compute tooltip boundaries)Numner700
tooltipWidthTooltip fixed widthNumber220
horizontalMouseMarginTooltip horizontal distance from mouse pointerNumber40
verticalBorderMarginTooltip min distance from chart top and bottom bordersNumber10
headerFormatterTooltip header formatter function. Arguments - selected interpolated date and chart dataset valuesFunction(selectedDate, data) => d3.timeFormat('%Y-%d-%m %H:%M:%S')(selectedDate)
topicFormatterTooltip path data description formatterFunction(data) => data.name
valueFormatterTooltip path data value formatterFunction(data) => d3.format('.1f')(data.interpolatedValue)
sortTooltip path data sorting function. First value will be displayed on top of tooltipFunction(a, b) => 0
Methods
NameDescriptionArguments
removeHide tooltipNone
showShow tooltip{ x: number, y: number, selectedDate: Date, data: ChartLinePointData[] }

TODO

  • Tests
  • JSDoc
  • Documentation
  • Display curve single points in missing data range and add them to tooltip
1.3.1

6 years ago

1.3.0

7 years ago

1.2.4

7 years ago

1.2.3

7 years ago

1.2.2

7 years ago

1.2.1

7 years ago

1.2.0

7 years ago

1.1.5

7 years ago

1.1.4

7 years ago

1.1.3

7 years ago

1.1.2

7 years ago

1.1.1

7 years ago

1.1.0

7 years ago

1.0.7

7 years ago

1.0.6

7 years ago

1.0.5

7 years ago

1.0.4

7 years ago

1.0.3

7 years ago

1.0.2

7 years ago

1.0.1

7 years ago

1.0.0

7 years ago