Line chart
TIP
For core principles, concept description, API and changelog, refer to the D3 chart.
Basic usage
import { Chart } from '@semcore/ui/d3-chart';
import React from 'react';
import LineMockData from './mock';
const Demo = () => {
return (
<Chart.Line
data={data}
plotWidth={500}
plotHeight={200}
groupKey='x'
xTicksCount={data.length / 2}
aria-label='Line chart'
/>
);
};
const data = LineMockData.TwoLines;
export default Demo;
Line
Line charts are displayed using the Line component. Dots are the dots on the line chart.
import { Plot, Line, XAxis, YAxis, minMax } from '@semcore/ui/d3-chart';
import { scaleLinear } from 'd3-scale';
import React from 'react';
import LineMockData from './mock';
const Demo = () => {
const MARGIN = 40;
const width = 500;
const height = 300;
const xScale = scaleLinear()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'x'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain([0, 10]);
return (
<Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
<YAxis>
<YAxis.Ticks />
<YAxis.Grid />
</YAxis>
<XAxis>
<XAxis.Ticks />
</XAxis>
<Line x='x' y='y'>
<Line.Dots display />
</Line>
</Plot>
);
};
const data = LineMockData.Default;
export default Demo;
Line with area
To get line with area, define y0 and y1 in Line.Area props and in the data.
import { Plot, Line, XAxis, YAxis, minMax } from '@semcore/ui/d3-chart';
import { scaleLinear } from 'd3-scale';
import React from 'react';
import LineMockData from './mock';
const Demo = () => {
const MARGIN = 40;
const width = 500;
const height = 300;
const xScale = scaleLinear()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'x'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain([0, 10]);
return (
<Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
<YAxis>
<YAxis.Ticks />
<YAxis.Grid />
</YAxis>
<XAxis>
<XAxis.Ticks />
</XAxis>
<Line x='x' y='y'>
<Line.Area y0='y0' y1='y1' />
</Line>
</Plot>
);
};
const data = LineMockData.Area;
export default Demo;
Hover line
- The
HoverLinecomponent is responsible for the hover effect. Use it with line charts. - You can set the orientation of the component using the
verticalandhorizontalproperties.
import { Plot, XAxis, YAxis, HoverLine, minMax } from '@semcore/ui/d3-chart';
import { scaleLinear } from 'd3-scale';
import React from 'react';
import LineMockData from './mock';
const Demo = () => {
const MARGIN = 40;
const width = 500;
const height = 300;
const xScale = scaleLinear()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'x'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain(minMax(data, 'y'));
return (
<Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
<YAxis>
<YAxis.Ticks />
</YAxis>
<XAxis>
<XAxis.Ticks />
</XAxis>
<HoverLine x='x' y='y' />
</Plot>
);
};
const data = LineMockData.Hover;
export default Demo;
Tooltip
You can add a tooltip to any element of a chart. The internal content can be easily identified with a function.
import { Flex } from '@semcore/ui/base-components';
import { Plot, Line, XAxis, YAxis, HoverLine, minMax } from '@semcore/ui/d3-chart';
import { Text } from '@semcore/ui/typography';
import { scaleLinear } from 'd3-scale';
import React from 'react';
import LineMockData from './mock';
const Demo = () => {
const MARGIN = 40;
const width = 500;
const height = 300;
const xScale = scaleLinear()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'x'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain([0, 10]);
return (
<Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
<YAxis>
<YAxis.Ticks />
<YAxis.Grid />
</YAxis>
<XAxis>
<XAxis.Ticks />
</XAxis>
<HoverLine.Tooltip x='x' wMin={100}>
{({ xIndex }) => {
return {
children: (
<>
<HoverLine.Tooltip.Title>{data[xIndex].x}</HoverLine.Tooltip.Title>
<Flex justifyContent='space-between'>
<HoverLine.Tooltip.Dot mr={4}>Line</HoverLine.Tooltip.Dot>
<Text bold>{data[xIndex].y}</Text>
</Flex>
</>
),
};
}}
</HoverLine.Tooltip>
<Line x='x' y='y'>
<Line.Dots />
</Line>
</Plot>
);
};
const data = LineMockData.Default;
export default Demo;
Time
Use scaleTime for calculating intermediate date values. See the d3 Time Scales documentation for more information.
TIP
If you already have the tick values, you can use scaleLine.
import { Flex } from '@semcore/ui/base-components';
import { Plot, Line, XAxis, YAxis, HoverLine, minMax } from '@semcore/ui/d3-chart';
import { Text } from '@semcore/ui/typography';
import { scaleLinear, scaleTime } from 'd3-scale';
import React from 'react';
import LineMockData from './mock';
function formatDate(value: any, options: any) {
return new Intl.DateTimeFormat('en', options).format(value);
}
const Demo = () => {
const MARGIN = 40;
const width = 500;
const height = 300;
const xScale = scaleTime()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'time'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain([0, 10]);
return (
<Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
<YAxis>
<YAxis.Ticks />
<YAxis.Grid />
</YAxis>
<XAxis>
<XAxis.Ticks>
{({ value }) => ({
children: formatDate(value, {
month: 'short',
day: 'numeric',
}),
})}
</XAxis.Ticks>
</XAxis>
<HoverLine.Tooltip x='time' wMin={100}>
{({ xIndex }) => {
return {
children: (
<>
<HoverLine.Tooltip.Title>
{formatDate(data[xIndex].time, {
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</HoverLine.Tooltip.Title>
<Flex justifyContent='space-between'>
<HoverLine.Tooltip.Dot mr={4}>Line</HoverLine.Tooltip.Dot>
<Text bold>{data[xIndex].line}</Text>
</Flex>
</>
),
};
}}
</HoverLine.Tooltip>
<Line x='time' y='line'>
<Line.Dots display />
</Line>
</Plot>
);
};
const data = LineMockData.Time;
export default Demo;
Curve
To get curved lines, transfer curve property with the required rounding method to the chart. You can find all available methods in the d3 Curves documentation.
import { Flex } from '@semcore/ui/base-components';
import { Plot, Line, XAxis, YAxis, HoverLine, minMax } from '@semcore/ui/d3-chart';
import { Text } from '@semcore/ui/typography';
import { scaleLinear } from 'd3-scale';
import { curveCardinal } from 'd3-shape';
import React from 'react';
import LineMockData from './mock';
const Demo = () => {
const MARGIN = 40;
const width = 500;
const height = 300;
const xScale = scaleLinear()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'x'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain([0, 10]);
return (
<Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
<YAxis>
<YAxis.Ticks />
<YAxis.Grid />
</YAxis>
<XAxis>
<XAxis.Ticks />
</XAxis>
<HoverLine.Tooltip x='x' wMin={100}>
{({ xIndex }) => {
return {
children: (
<>
<HoverLine.Tooltip.Title>{data[xIndex].x}</HoverLine.Tooltip.Title>
<Flex justifyContent='space-between'>
<HoverLine.Tooltip.Dot mr={4}>Line</HoverLine.Tooltip.Dot>
<Text bold>{data[xIndex].y}</Text>
</Flex>
</>
),
};
}}
</HoverLine.Tooltip>
<Line x='x' y='y' curve={curveCardinal}>
<Line.Dots />
</Line>
</Plot>
);
};
const data = LineMockData.Default;
export default Demo;
Partial dots display
You can pass function to display prop of Dots component to control which dots should be displayed.
import { Plot, Line, XAxis, YAxis, minMax } from '@semcore/ui/d3-chart';
import { scaleLinear } from 'd3-scale';
import { curveCardinal } from 'd3-shape';
import React from 'react';
import LineMockData from './mock';
const displayDots = (index: number, active: boolean, single: boolean) => {
if (single || active) return true;
return index < 10;
};
const Demo = () => {
const MARGIN = 40;
const width = 500;
const height = 300;
const xScale = scaleLinear()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'x'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain([0, 10]);
return (
<Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
<YAxis>
<YAxis.Ticks />
<YAxis.Grid />
</YAxis>
<XAxis>
<XAxis.Ticks />
</XAxis>
<Line x='x' y='y' curve={curveCardinal}>
<Line.Dots display={displayDots} />
</Line>
</Plot>
);
};
const data = LineMockData.Default;
export default Demo;
Legend and symbols for dots
To make data available without relying only on colors (for example, for different kinds of colorblind and high-contrast modes), use the patterns property. With this property enabled lines become dashed and change dots to different symbols.
Note that for ChartLegend patterns property works only with default shape={'Checkbox'}.
import { Flex } from '@semcore/ui/base-components';
import {
Line,
minMax,
Plot,
XAxis,
YAxis,
ChartLegend,
makeDataHintsContainer,
} from '@semcore/ui/d3-chart';
import { scaleLinear } from 'd3-scale';
import React from 'react';
import LineMockData from './mock';
const dataHints = makeDataHintsContainer();
const Demo = () => {
const MARGIN = 30;
const width = 500;
const height = 300;
const xScale = scaleLinear()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'x'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain([0, 10]);
const [legendItems, setLegendItems] = React.useState(
Object.keys(data[0])
.filter((name) => name !== 'x')
.map((item, index) => {
return {
id: item,
label: `Line ${index + 1}`,
checked: true,
color: `chart-palette-order-${index + 1}`,
};
}),
);
const [highlightedLine, setHighlightedLine] = React.useState(-1);
const handleChangeVisible = React.useCallback((id: string, isVisible: boolean) => {
setLegendItems((prevItems) => {
return prevItems.map((item) => {
if (item.id === id) {
item.checked = isVisible;
}
return item;
});
});
}, []);
const handleMouseEnter = React.useCallback((id: string) => {
setHighlightedLine(legendItems.findIndex((line) => line.id === id));
}, []);
const handleMouseLeave = React.useCallback(() => {
setHighlightedLine(-1);
}, []);
return (
<Flex direction='column'>
<ChartLegend
dataHints={dataHints}
items={legendItems}
onChangeVisibleItem={handleChangeVisible}
onMouseEnterItem={handleMouseEnter}
onMouseLeaveItem={handleMouseLeave}
patterns
aria-label='Patterned chart legend'
/>
<Plot
data={data}
scale={[xScale, yScale]}
width={width}
height={height}
dataHints={dataHints}
patterns
>
<YAxis>
<YAxis.Ticks ticks={yScale.ticks(4)} />
<YAxis.Grid ticks={yScale.ticks(4)} />
</YAxis>
<XAxis>
<XAxis.Ticks ticks={xScale.ticks(5)} />
</XAxis>
{legendItems.map((item, index) => {
return (
item.checked && (
<Line
x='x'
y={item.id}
key={item.id}
color={item.color}
transparent={highlightedLine !== -1 && highlightedLine !== index}
>
<Line.Dots display />
</Line>
)
);
})}
</Plot>
</Flex>
);
};
const data = LineMockData.ThreeLines;
export default Demo;
Interpolation
If exact values of specific point is not available, you can pass interpolateValue and value will be automatically interpolated.
import { Plot, Line, XAxis, YAxis, minMax } from '@semcore/ui/d3-chart';
import { scaleLinear } from 'd3-scale';
import React from 'react';
import LineMockData from './mock';
const Demo = () => {
const MARGIN = 40;
const width = 500;
const height = 300;
const xScale = scaleLinear()
.range([MARGIN, width - MARGIN])
.domain(minMax(data, 'x'));
const yScale = scaleLinear()
.range([height - MARGIN, MARGIN])
.domain([0, 10]);
return (
<Plot data={data} scale={[xScale, yScale]} width={width} height={height}>
<YAxis>
<YAxis.Ticks />
<YAxis.Grid />
</YAxis>
<XAxis>
<XAxis.Ticks />
</XAxis>
<Line x='x' y='line1'>
<Line.Dots display />
</Line>
<Line x='x' y='line2'>
<Line.Dots display />
</Line>
</Plot>
);
};
const data = LineMockData.Interpolation;
export default Demo;