Created
November 15, 2020 11:45
-
-
Save rakibulalam/658ad640c4d5cb7501979bf411506f17 to your computer and use it in GitHub Desktop.
Line chart , D3, React, TypeScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { extent, group, max } from 'd3-array'; | |
import { | |
ScaleLinear, | |
scaleLinear, | |
ScaleOrdinal, | |
scaleOrdinal, | |
ScaleTime, | |
scaleTime | |
} from 'd3-scale'; | |
import { select } from 'd3-selection'; | |
import { curveBasis, line } from 'd3-shape'; | |
import React, { | |
CSSProperties, | |
Fragment, | |
MutableRefObject, | |
useEffect, | |
useRef | |
} from 'react'; | |
import './line-chart.scss'; | |
export type LineChartDataType = { | |
label?: string; | |
value: number; | |
dateTime: string; | |
borderColor?: string; | |
borderWidth?: number; | |
backgroundColor?: string; | |
}; | |
/* eslint-disable-next-line */ | |
export interface LineChartProps { | |
data: LineChartDataType[]; // data is collection of array | |
size: number[]; // size represents here width and height of the bar chart | |
paddingInner?: number; // its consider to distance between bars | |
style?: CSSProperties; // its consider to add style to change svg | |
strokeWidth?:number; // | |
} | |
const LineChartDataTypeDefault: LineChartDataType[] = [ | |
{ | |
label: '12/12/2002', | |
value: 1, | |
borderColor: '#fff', | |
borderWidth: 2, | |
backgroundColor: '#555', | |
dateTime: '10/10/2002', | |
}, | |
]; | |
/** | |
* | |
* @param LineChartProps | |
* @component LineChart | |
* @description Its line chart based on days and hours. | |
* @author Md. Rakibul Alam | |
* @contact https://github.com/rakibulalam71 | |
*/ | |
export const LineChart = ({ | |
data = LineChartDataTypeDefault, | |
size = [200, 200], | |
strokeWidth = 1.5, | |
style, | |
}: LineChartProps) => { | |
const chartRef: MutableRefObject<undefined> = useRef(); | |
const tooltipRef: MutableRefObject<undefined> = useRef(); | |
const [width, height] = size; | |
useEffect(() => { | |
const node = chartRef.current; | |
/** dataGroupByday is divided the data into two parts yestarday and today etc. it can possible to add mulitple days data */ | |
/** Map<number, LineChartDataType[]> =Map<days, LineChartDataType[] */ | |
const dataGroupByDay:Map<number, LineChartDataType[]> = group(data, ({ dateTime }) => | |
new Date(dateTime).getDay() | |
); | |
/** find the max value of the data */ | |
const valueMax: number = max(data.map(({ value }) => value)); | |
/** xScale is maintain the time consistency of each hours */ | |
const xScale:ScaleTime<number, number, never> = scaleTime() | |
.domain( | |
extent( | |
data.map(({ dateTime }: LineChartDataType) => { | |
return new Date(dateTime).getHours(); | |
}) | |
) | |
) | |
.range([0, width]); | |
/** yScale actualy is keeping height consistency based on max domain value */ | |
const yScale: ScaleLinear<number, number, never> = scaleLinear() | |
.domain([0, valueMax]) | |
.range([height, 0]); | |
/** days belongs of every keys of map methods */ | |
const days: string[] = [...dataGroupByDay.keys()].map(String); | |
/** ordinal scale for line color for each key of map. key is actualy treated here each days */ | |
const colorScale:ScaleOrdinal<string, unknown, never> = scaleOrdinal() | |
.domain(days) | |
.range([ | |
'#26b1bb', | |
'#377eb8', | |
'#4daf4a', | |
'#984ea3', | |
'#ff7f00', | |
'#ffff33', | |
'#a65628', | |
'#f781bf', | |
'#999999', | |
]); | |
select(node) | |
.selectAll('path') | |
.data(dataGroupByDay) | |
.enter() | |
.append('path') | |
.attr('fill', 'none') | |
.attr('stroke', ([key]:Map<number, LineChartDataType[]>): string => { | |
return colorScale(key.toString()) as string; | |
}) | |
.attr('stroke-width', strokeWidth) | |
.attr('d', ([, values]: Map<number, LineChartDataType[]>) => { | |
return line() | |
.x(({ dateTime }: LineChartDataType) => { | |
return xScale(new Date(dateTime).getHours()); | |
}) | |
.y(({ value }: LineChartDataType) => { | |
return yScale(value); | |
}) | |
.curve(curveBasis)(values as []); | |
}); | |
}, []); | |
return ( | |
<Fragment> | |
<svg style={style} ref={chartRef} width={width} height={height}></svg> | |
</Fragment> | |
); | |
}; | |
export default LineChart; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment