-
Notifications
You must be signed in to change notification settings - Fork 1
/
LineChart.tsx
93 lines (80 loc) · 2.73 KB
/
LineChart.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import * as React from "react";
import * as d3 from "d3";
import Chart from "../components/Chart";
import Line from "../components/Line";
import Axis from "../components/Axis";
import type { BoundedDimensions } from "../utils/types";
import type { WeatherData } from "../hooks/useWeatherData";
//* Step 1b. Access Data
const dateParser = d3.timeParse("%Y-%m-%d");
const xAccessor = (d: WeatherData) => dateParser(d.date) as Date;
const yAccessor = (d: WeatherData) => d.temperatureMax;
//* Step 2. Create chart dimensions
const dimensions: BoundedDimensions = {
width: window.innerWidth * 0.9,
height: 400,
margin: {
top: 15,
right: 15,
bottom: 40,
left: 60,
},
boundedWidth: 0,
boundedHeight: 0,
};
dimensions.boundedWidth =
dimensions.width - dimensions.margin.left - dimensions.margin.right;
dimensions.boundedHeight =
dimensions.height - dimensions.margin.top - dimensions.margin.bottom;
const formatTimelineDate = d3.timeFormat("%B");
function LineChart({ dataset }: { dataset: WeatherData[] }) {
//* Step 4. Create scales
const xScale = d3
.scaleTime()
.domain(d3.extent(dataset, xAccessor) as [Date, Date])
.range([0, dimensions.boundedWidth]);
const yScale = d3
.scaleLinear()
.domain(d3.extent(dataset, yAccessor) as [number, number])
.range([dimensions.boundedHeight, 0]);
const xAccessorScaled = (d: WeatherData) => xScale(xAccessor(d));
const yAccessorScaled = (d: WeatherData) => yScale(yAccessor(d));
// const y0AccessorScaled = () => yScale(yScale.domain()[0]);
const freezingTemperaturePlacement = yScale(32);
//* Notice how React lets us draw everything we need for the charts
//* in such a nice, declarative way
//* We can also abstract common steps in separate reusable components
//* to make our workflow a lot easier!
return (
<div>
{/* Step 3. Draw canvas */}
<Chart dimensions={dimensions}>
<rect
x="0"
width={dimensions.boundedWidth}
y={freezingTemperaturePlacement}
height={dimensions.boundedHeight - freezingTemperaturePlacement}
fill="hsl(180deg 44% 92%)"
/>
{/* Step 5. Draw data */}
<Line
data={dataset}
xAccessor={xAccessorScaled}
yAccessor={yAccessorScaled}
/>
{/* <Line
type="area"
data={dataset}
xAccessor={xAccessorScaled}
yAccessor={yAccessorScaled}
y0Accessor={y0AccessorScaled}
style={{ fill: "hsl(41deg 35% 52% / 0.185)" }}
/> */}
{/* Step 6. Draw peripherals */}
<Axis dimension="x" scale={xScale} formatTick={formatTimelineDate} />
<Axis dimension="y" scale={yScale} />
</Chart>
</div>
);
}
export default LineChart;