first line graph version

This commit is contained in:
Rebecca-Chou 2022-06-15 17:24:08 -04:00
parent 591b885ae2
commit 6c59b76560
5 changed files with 342 additions and 8 deletions

144
components/LineGraph.tsx Normal file
View File

@ -0,0 +1,144 @@
import { AxisLeft, AxisBottom } from "@visx/axis";
import { bottomTickLabelProps } from "@visx/axis/lib/axis/AxisBottom";
import { curveLinear } from "@visx/curve";
import { GridRows, GridColumns } from "@visx/grid";
import { Group } from "@visx/group";
import { scaleBand, scaleLinear } from "@visx/scale";
import { LinePath } from "@visx/shape";
import React from "react";
export const background = "#252D41";
interface LineGraphData {
x: string;
y: number;
}
interface BarGraphProps {
data: LineGraphData[];
width: number;
height: number;
margin: {
top: number;
bottom: number;
left: number;
right: number;
};
}
const COLOURS = {
salmon: "#ffcad0",
navy: "#2c3651",
white: "#ffffff",
pink: "#ef83b1",
darkpink: "#cc5773",
};
const defaultMargin = { top: 40, right: 30, bottom: 50, left: 40 };
export default function LineGraph({
data,
width,
height,
margin = defaultMargin,
}: BarGraphProps) {
if (width < 10) return null;
// bounds
const xMax = width - margin.left - margin.right - 15;
const yMax = height - margin.top - margin.bottom - 15;
// accessors
const getX = (d: LineGraphData) => d.x;
const getY = (d: LineGraphData) => d.y;
// scales
const xScale = scaleBand({
range: [0, xMax],
domain: data.map(getX),
});
const yScale = scaleLinear({
range: [yMax, 0],
nice: true,
domain: [0, 100],
// domain: [0, Math.max(...data.map(getY))],
});
const xPoint = (d: LineGraphData) => xScale(getX(d));
const yPoint = (d: LineGraphData) => yScale(getY(d));
console.log(xPoint);
return (
<div>
<svg width={width} height={height}>
<rect
x={0}
y={0}
width={width}
height={height}
fill={background}
rx={14}
/>
<Group left={margin.left} top={margin.top}>
<GridRows
left={30}
scale={yScale}
width={xMax - 30}
height={yMax}
stroke="#354265"
/>
<GridColumns
scale={xScale}
width={xMax}
height={yMax}
stroke="#354265"
/>
<AxisBottom
top={yMax + 20}
scale={xScale}
hideAxisLine
hideTicks
tickLabelProps={() => {
return {
...bottomTickLabelProps(),
fill: COLOURS.white,
fontSize: "1rem",
fontFamily: "Inconsolata",
fontWeight: 800,
};
}}
/>
<AxisLeft
scale={yScale}
hideAxisLine
hideTicks
tickLabelProps={() => {
return {
...bottomTickLabelProps(),
fill: COLOURS.white,
fontSize: "1rem",
fontFamily: "Inconsolata",
fontWeight: 800,
};
}}
/>
<text x="15" y="5" fontSize={10} color={COLOURS.white}>
(%)
</text>
{/* BUG: alignment with x-axis */}
<LinePath
data={data}
curve={curveLinear}
x={xPoint}
y={yPoint}
translate={margin.left}
stroke="#EF839D"
strokeWidth={1.5}
/>
</Group>
</svg>
</div>
);
}

View File

@ -35,3 +35,30 @@ export const mockCategoricalData = [
value: 29,
},
];
export const mockLineGraphlData = [
{
x: "1A",
y: 80,
},
{
x: "1B",
y: 84,
},
{
x: "2A",
y: 90,
},
{
x: "2B",
y: 70,
},
{
x: "3A",
y: 60,
},
{
x: "3B",
y: 80,
},
];

157
package-lock.json generated
View File

@ -10,12 +10,16 @@
"dependencies": {
"@visx/axis": "^2.10.0",
"@visx/grid": "^2.10.0",
"@visx/mock-data": "^2.1.2",
"@visx/shape": "^2.10.0",
"@visx/threshold": "^2.10.0",
"d3-array": "^3.1.6",
"next": "12.1.6",
"react": "18.1.0",
"react-dom": "18.1.0"
},
"devDependencies": {
"@types/d3-array": "^3.0.3",
"@types/node": "17.0.38",
"@types/react": "18.0.10",
"@types/react-dom": "18.0.5",
@ -571,6 +575,12 @@
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
"dev": true
},
"node_modules/@types/d3-array": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.3.tgz",
"integrity": "sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ==",
"dev": true
},
"node_modules/@types/d3-color": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.4.2.tgz",
@ -589,6 +599,11 @@
"resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ=="
},
"node_modules/@types/d3-random": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-2.2.1.tgz",
"integrity": "sha512-5vvxn6//poNeOxt1ZwC7QU//dG9QqABjy1T7fP/xmFHY95GnaOw3yABf29hiu5SR1Oo34XcpyHFbzod+vemQjA=="
},
"node_modules/@types/d3-scale": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-3.3.2.tgz",
@ -886,6 +901,18 @@
"react": "^16.3.0-0 || ^17.0.0-0 || ^18.0.0-0"
}
},
"node_modules/@visx/clip-path": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/@visx/clip-path/-/clip-path-2.10.0.tgz",
"integrity": "sha512-YIUQstsHKGysyDISOV5p+fMymkUdHCs89nSY/w6TG9EIl8x2jRhrQdojwtCYvjLkPZiZiKa8MBT6fFzsSfGImg==",
"dependencies": {
"@types/react": "*",
"prop-types": "^15.5.10"
},
"peerDependencies": {
"react": "^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0"
}
},
"node_modules/@visx/curve": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@visx/curve/-/curve-2.1.0.tgz",
@ -926,6 +953,15 @@
"react": "^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0"
}
},
"node_modules/@visx/mock-data": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@visx/mock-data/-/mock-data-2.1.2.tgz",
"integrity": "sha512-6xUVP56tiPwVi3BxvoXPQzDYWG6iX2nnOlsHEYsHgK8gHq1r7AhjQtdbQUX7QF0QkmkJM0cW8TBjZ2e+dItB8Q==",
"dependencies": {
"@types/d3-random": "^2.2.0",
"d3-random": "^2.2.2"
}
},
"node_modules/@visx/point": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@visx/point/-/point-2.6.0.tgz",
@ -982,6 +1018,21 @@
"react": "^16.3.0-0 || ^17.0.0-0 || ^18.0.0-0"
}
},
"node_modules/@visx/threshold": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/@visx/threshold/-/threshold-2.10.0.tgz",
"integrity": "sha512-wFYB0Q7la1CT5qpUjyFQ+aJALWIRPOO+BNCBhYDfL8Lqk7IpXOaHUiaCG05DM/212NHaxNtHbRPp00qLoUFLyg==",
"dependencies": {
"@types/react": "*",
"@visx/clip-path": "2.10.0",
"@visx/shape": "2.10.0",
"classnames": "^2.3.1",
"prop-types": "^15.5.10"
},
"peerDependencies": {
"react": "^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0"
}
},
"node_modules/acorn": {
"version": "8.7.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
@ -1422,11 +1473,14 @@
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
},
"node_modules/d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.1.6.tgz",
"integrity": "sha512-DCbBBNuKOeiR9h04ySRBMW52TFVc91O9wJziuyXw6Ztmy8D3oZbmCkOO3UHKC7ceNJsN2Mavo9+vwV8EAEUXzA==",
"dependencies": {
"internmap": "^1.0.0"
"internmap": "1 - 2"
},
"engines": {
"node": ">=12"
}
},
"node_modules/d3-color": {
@ -1452,6 +1506,11 @@
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
},
"node_modules/d3-random": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-2.2.2.tgz",
"integrity": "sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw=="
},
"node_modules/d3-scale": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz",
@ -1464,6 +1523,14 @@
"d3-time-format": "2 - 3"
}
},
"node_modules/d3-scale/node_modules/d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
"dependencies": {
"internmap": "^1.0.0"
}
},
"node_modules/d3-shape": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
@ -1488,6 +1555,14 @@
"d3-time": "1 - 2"
}
},
"node_modules/d3-time/node_modules/d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
"dependencies": {
"internmap": "^1.0.0"
}
},
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@ -4659,6 +4734,12 @@
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
"dev": true
},
"@types/d3-array": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.3.tgz",
"integrity": "sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ==",
"dev": true
},
"@types/d3-color": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.4.2.tgz",
@ -4677,6 +4758,11 @@
"resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ=="
},
"@types/d3-random": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-2.2.1.tgz",
"integrity": "sha512-5vvxn6//poNeOxt1ZwC7QU//dG9QqABjy1T7fP/xmFHY95GnaOw3yABf29hiu5SR1Oo34XcpyHFbzod+vemQjA=="
},
"@types/d3-scale": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-3.3.2.tgz",
@ -4878,6 +4964,15 @@
"prop-types": "^15.6.0"
}
},
"@visx/clip-path": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/@visx/clip-path/-/clip-path-2.10.0.tgz",
"integrity": "sha512-YIUQstsHKGysyDISOV5p+fMymkUdHCs89nSY/w6TG9EIl8x2jRhrQdojwtCYvjLkPZiZiKa8MBT6fFzsSfGImg==",
"requires": {
"@types/react": "*",
"prop-types": "^15.5.10"
}
},
"@visx/curve": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@visx/curve/-/curve-2.1.0.tgz",
@ -4912,6 +5007,15 @@
"prop-types": "^15.6.2"
}
},
"@visx/mock-data": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@visx/mock-data/-/mock-data-2.1.2.tgz",
"integrity": "sha512-6xUVP56tiPwVi3BxvoXPQzDYWG6iX2nnOlsHEYsHgK8gHq1r7AhjQtdbQUX7QF0QkmkJM0cW8TBjZ2e+dItB8Q==",
"requires": {
"@types/d3-random": "^2.2.0",
"d3-random": "^2.2.2"
}
},
"@visx/point": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@visx/point/-/point-2.6.0.tgz",
@ -4962,6 +5066,18 @@
"reduce-css-calc": "^1.3.0"
}
},
"@visx/threshold": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/@visx/threshold/-/threshold-2.10.0.tgz",
"integrity": "sha512-wFYB0Q7la1CT5qpUjyFQ+aJALWIRPOO+BNCBhYDfL8Lqk7IpXOaHUiaCG05DM/212NHaxNtHbRPp00qLoUFLyg==",
"requires": {
"@types/react": "*",
"@visx/clip-path": "2.10.0",
"@visx/shape": "2.10.0",
"classnames": "^2.3.1",
"prop-types": "^15.5.10"
}
},
"acorn": {
"version": "8.7.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
@ -5247,11 +5363,11 @@
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
},
"d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.1.6.tgz",
"integrity": "sha512-DCbBBNuKOeiR9h04ySRBMW52TFVc91O9wJziuyXw6Ztmy8D3oZbmCkOO3UHKC7ceNJsN2Mavo9+vwV8EAEUXzA==",
"requires": {
"internmap": "^1.0.0"
"internmap": "1 - 2"
}
},
"d3-color": {
@ -5277,6 +5393,11 @@
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
},
"d3-random": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-2.2.2.tgz",
"integrity": "sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw=="
},
"d3-scale": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.3.0.tgz",
@ -5287,6 +5408,16 @@
"d3-interpolate": "1.2.0 - 2",
"d3-time": "^2.1.1",
"d3-time-format": "2 - 3"
},
"dependencies": {
"d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
"requires": {
"internmap": "^1.0.0"
}
}
}
},
"d3-shape": {
@ -5303,6 +5434,16 @@
"integrity": "sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==",
"requires": {
"d3-array": "2"
},
"dependencies": {
"d3-array": {
"version": "2.12.1",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
"integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
"requires": {
"internmap": "^1.0.0"
}
}
}
},
"d3-time-format": {

View File

@ -17,12 +17,16 @@
"dependencies": {
"@visx/axis": "^2.10.0",
"@visx/grid": "^2.10.0",
"@visx/mock-data": "^2.1.2",
"@visx/shape": "^2.10.0",
"@visx/threshold": "^2.10.0",
"d3-array": "^3.1.6",
"next": "12.1.6",
"react": "18.1.0",
"react-dom": "18.1.0"
},
"devDependencies": {
"@types/d3-array": "^3.0.3",
"@types/node": "17.0.38",
"@types/react": "18.0.10",
"@types/react-dom": "18.0.5",

View File

@ -1,10 +1,28 @@
import { mockLineGraphlData } from "data/mocks";
import React from "react";
import LineGraph from "@/components/LineGraph";
export default function Home() {
return (
<>
<h1>Playground</h1>
<p>Show off your components here!</p>
<h2>
<code>{"<LineGraph />"}</code>
</h2>
<LineGraph
// className={styles.barGraphDemo}
data={mockLineGraphlData}
width={700}
height={400}
margin={{
top: 20,
bottom: 40,
left: 50,
right: 20,
}}
/>
</>
);
}