Commit 622eecb4 authored by Yoon, Daeki's avatar Yoon, Daeki 😅
Browse files

불필요한 파일 제거 및 필요한 패키지 설치

parent 928486a6
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
"author": "Daeki Yoon", "author": "Daeki Yoon",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/d3": "^7.4.0",
"@types/react": "^18.0.14", "@types/react": "^18.0.14",
"@types/react-dom": "^18.0.5", "@types/react-dom": "^18.0.5",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
...@@ -29,7 +30,12 @@ ...@@ -29,7 +30,12 @@
"webpack-dev-server": "^4.9.2" "webpack-dev-server": "^4.9.2"
}, },
"dependencies": { "dependencies": {
"@juggle/resize-observer": "^3.4.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"d3": "^7.8.0",
"d3-axis": "^3.0.0",
"d3-scale": "^4.0.2",
"d3-shape": "^3.2.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router-dom": "^6.3.0" "react-router-dom": "^6.3.0"
......
import React, { useEffect, useRef, useState } from "react";
import { scaleLinear } from "d3-scale";
import { max, min, axisBottom, select } from "d3";
import { generateRandomDataset } from "../helpers";
export const AxisCirclesD3 = () => {
const [dataset, setDataset] = useState(generateRandomDataset(30, 1));
const ref = useRef(null);
const width = 100,
height = 50,
r = 1;
const xPad = 3,
yPad = 3;
const xMin = min(dataset, (d) => d[0]) || 0;
const xMax = max(dataset, (d) => d[0]) || 100;
const yMin = min(dataset, (d) => d[1]) || 0;
const yMax = max(dataset, (d) => d[1]) || 50;
useEffect(() => {
const xScale = scaleLinear()
.domain([xMin, xMax])
.range([0 + xMin, width - xPad]);
const yScale = scaleLinear()
.domain([yMin, yMax])
.range([yMin, height - yPad]);
const rScale = scaleLinear()
.domain([xMin + yMin, xMax + yMax])
.range([0, height / 10]);
const svgElmt = select(ref.current);
const xAxis = axisBottom(xScale);
svgElmt.append("g").call(xAxis);
}, []);
return (
<div style={{ backgroundColor: "gray" }}>
<svg ref={ref} viewBox={`0 0 ${width + xMin} ${height + 3}`}></svg>
</div>
);
};
import { Axis, Orient } from "./Axis";
import { BottomAxis } from "./BottomAxis";
import rawData from "../data/data.json";
import { scaleUtc, scaleLinear } from "d3-scale";
import { line } from "d3-shape";
import { max, extent } from "d3";
import useResizeObserver from "../hooks/useResizeObserver";
import { useSize } from "../hooks/useSize";
import { useRef } from "react";
import { useChartDimensions } from "../hooks/useChartDimensions";
import { Comment } from "../commons";
type Record = {
date: Date;
value: number;
};
const data = rawData.map((d: any) => {
return {
date: new Date(d.date),
value: +d.value,
};
}) as Record[];
export const AxisExamples = () => {
const [target, dimensions] = useChartDimensions({
marginTop: 20,
marginBottom: 30,
marginLeft: 30,
marginRight: 20,
});
// console.log("dimensions height=", dimensions.height);
// const target = useRef(null);
// const size = useSize(target);
// console.log("size height=", size?.height);
// const width = 600;
// const height = 400;
const width = dimensions.width || 600;
const height = dimensions.height || 400;
const margin = {
top: dimensions.marginTop,
right: dimensions.marginRight,
bottom: dimensions.marginBottom,
left: dimensions.marginLeft,
};
// const width = size?.width || 600;
// const height = size?.height || 400;
// const margin = {
// top: 20,
// right: 20,
// bottom: 30,
// left: 30,
// };
const x = scaleUtc()
.domain(extent(data, (d) => d.date) as [Date, Date])
.range([margin.left, width - margin.right]);
const y = scaleLinear<number>()
.domain([0, max(data, (d) => d.value)] as [number, number])
.nice()
.range([height - margin.bottom, margin.top]);
const lineXY = line<Record>()
.defined((d) => !isNaN(d.value))
.x((d) => x(d.date))
.y((d) => y(d.value));
return (
<div>
<h1 className="text-3xl">Axis Examples</h1>
<Comment>Resizable element 적용</Comment>
<div ref={target} style={{ height: "80vh", border: "1px solid black" }}>
<svg width={width} height={height}>
<path
fill="none"
stroke="steelblue"
strokeWidth="1.5"
strokeLinejoin="round"
strokeLinecap="round"
d={lineXY(data) as string}
/>
<g transform={`translate(${margin.left},0)`}>
<Axis scale={y} orient={Orient.left} />
</g>
<g transform={`translate(0,${height - margin.bottom})`}>
<Axis scale={x} orient={Orient.bottom} />
</g>
</svg>
</div>
</div>
);
};
export { AxisExamples } from "./AxisExamples";
export { AxisScaleLinear } from "./AxisScaleLinear"; export { AxisScaleLinear } from "./AxisScaleLinear";
export { AxisVerticalScaleLinear } from "./AxisVerticalScaleLinear"; export { AxisVerticalScaleLinear } from "./AxisVerticalScaleLinear";
export { Axis, Orient } from "./Axis"; export { Axis, Orient } from "./Axis";
import React from "react";
import { max, min, range } from "d3"; import { max, min, range } from "d3";
import { scaleLinear, scaleBand } from "d3-scale"; import { scaleLinear, scaleBand } from "d3-scale";
import { BarText } from "../texts"; import { BarText } from "../texts";
......
import React from "react";
import { max, min, range } from "d3"; import { max, min, range } from "d3";
import { scaleLinear, scaleBand } from "d3-scale"; import { scaleLinear, scaleBand } from "d3-scale";
import { BarText } from "../texts"; import { BarText } from "../texts";
......
import { useRef, useState } from "react";
import { BarChart } from "./BarChart";
import { generateDataset1D } from "../helpers";
import { BarChartWithAnimation } from "./BarChartWithAnimation";
import { Button, Comment } from "../commons";
import { useSize } from "../hooks";
const initDataset = [
5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25,
];
const nextDataset = [
21, 16, 6, 18, 10, 18, 20, 9, 17, 1, 5, 11, 18, 5, 2, 22, 7, 23, 3, 3,
];
export const BarExample = () => {
const [dataset, setDataset] = useState(initDataset);
const target = useRef(null);
const size = useSize(target);
const toggle = useRef(true);
const handleClick = () => {
setDataset(generateDataset1D());
};
const handleToggle = () => {
toggle.current ? setDataset(nextDataset) : setDataset(initDataset);
toggle.current = !toggle.current;
};
return (
<div>
<div className="my-4">
<Button className="mr-4" onClick={handleClick}>
새로운 무작위 데이터로 차트를 갱신하려면 클릭하세요.
</Button>
<Button onClick={handleToggle}>데이터 토글</Button>
</div>
<Comment>
애니메이션이 들어간 바차트. 문제는 텍스트가 같이 애니메이션이 안된다는
것입니다.
</Comment>
<BarChartWithAnimation dataset={dataset} />
<Comment>바차트</Comment>
<div ref={target}>
<BarChart dataset={dataset} dimensions={size} />
</div>
</div>
);
};
export { Bar } from "./Bar"; export { Bar } from "./Bar";
export { BarChart } from "./BarChart"; export { BarChart } from "./BarChart";
export { BarExample } from "./BarExample";
import React, { useRef, useState } from "react";
import { generateDataset1D } from "../helpers";
import { Pie } from "./Pie";
const initDataset = [50, 30, 12, 5, 3];
const nextDataset = [21, 16, 6, 18, 10];
export const PieExample = () => {
const [dataset, setDataset] = useState(initDataset);
const toggle = useRef(true);
const handleClick = () => {
setDataset(generateDataset1D());
};
const handleToggle = () => {
toggle.current ? setDataset(nextDataset) : setDataset(initDataset);
toggle.current = !toggle.current;
};
return (
<div>
<p onClick={handleClick}>새 데이터로 차트를 갱신하려면 클릭하세요</p>
<p onClick={handleToggle}>데이터 토글</p>
<Pie data={dataset} />
</div>
);
};
export { PieExample } from "./PieExample";
import { max, min } from "d3";
import { scaleLinear } from "d3-scale";
import React, { useState } from "react";
import { AxisScaleLinear, AxisVerticalScaleLinear } from "../axes";
import { CirclesWithG } from ".";
import { generateRandomDataset } from "../helpers";
import { TextsWithG } from "../texts";
export const ChartV0 = () => {
const pad = 30;
const margin = { top: 20, right: 30, bottom: 20, left: 30 };
const width = window.innerWidth - margin.left - margin.right;
const height = 300 - margin.bottom - margin.top;
const [dataset, setDataset] = useState(generateRandomDataset());
const xMin = min(dataset, (d) => d[0]) || 0;
const xMax = max(dataset, (d) => d[0]) || 100;
const yMin = min(dataset, (d) => d[1]) || 0;
const yMax = max(dataset, (d) => d[1]) || 100;
const xScale = scaleLinear()
.domain([0, xMax + 5])
.nice()
.range([0, width]);
const yScale = scaleLinear()
.domain([0, yMax + 5])
.nice()
.range([height, 0]);
const scaledDataset = dataset.map((d) => [xScale(d[0]), yScale(d[1])]);
// console.log("dataset:", dataset, "scaled dataset:", scaledDataset);
return (
<svg
width={width + margin.left + margin.right}
height={height + margin.bottom + margin.top}
>
<g transform={`translate(${margin.left}, ${margin.top})`}>
<CirclesWithG dataset={scaledDataset} />
<TextsWithG dataset={dataset} xScale={xScale} yScale={yScale} />
<AxisVerticalScaleLinear x={0} y={0} scale={yScale} />
<AxisScaleLinear x={0} y={height} scale={xScale} />
</g>
</svg>
);
};
import React, { useEffect, useRef, useState } from "react";
import { select } from "d3-selection";
import { generateDataset } from "../helpers";
export const CirclesWithD3 = () => {
const [dataset, setDataset] = useState(generateDataset());
const ref = useRef(null);
useEffect(() => {
const svg = select(ref.current);
svg
.selectAll("circle")
.data(dataset)
.join("circle")
.attr("cx", (d) => d[0])
.attr("cy", (d) => d[1])
.attr("r", 3);
}, [dataset]);
return <svg viewBox="0 0 100 50" ref={ref} />;
};
import React, { useState } from "react";
import { generateDataset, generateRandomDataset } from "../helpers";
export const CirclesWithSvg = () => {
const [dataset, setDataset] = useState(generateRandomDataset());
return (
<div>
<svg viewBox="0 0 100 50" style={{ backgroundColor: "red" }}>
{dataset.map((d) => (
<circle key={d[0]} cx={d[0]} cy={d[1]} r={3}></circle>
))}
</svg>
</div>
);
};
import React, { useState } from "react";
import { scaleLinear } from "d3-scale";
import { max, min } from "d3";
import { generateRandomDataset } from "../helpers";
export const ScaledCircles = () => {
const [dataset, setDataset] = useState(generateRandomDataset(30, 1));
console.log(`dataset:`, dataset);
const width = 100,
height = 50,
r = 1;
const xPad = 3,
yPad = 3;
const xMin = min(dataset, (d) => d[0]) || 0;
const xMax = max(dataset, (d) => d[0]) || 100;
const yMin = min(dataset, (d) => d[1]) || 0;
const yMax = max(dataset, (d) => d[1]) || 50;
const xScale = scaleLinear()
.domain([xMin, xMax])
.range([0 + xMin, width - xPad]);
const yScale = scaleLinear()
.domain([yMin, yMax])
.range([yMin, height - yPad]);
const rScale = scaleLinear()
.domain([xMin + yMin, xMax + yMax])
.range([0, height / 10]);
return (
<div style={{ backgroundColor: "gray" }}>
<svg viewBox={`0 0 ${width + xMin} ${height + 3}`}>
{dataset.map((d) => (
<circle
key={d[0]}
cx={xScale(d[0])}
cy={yScale(d[1])}
r={rScale(d[0] + d[1])}
></circle>
))}
</svg>
</div>
);
};
...@@ -7,8 +7,6 @@ import { ...@@ -7,8 +7,6 @@ import {
AxisVerticalScaleLinear, AxisVerticalScaleLinear,
Orient, Orient,
} from "../axes"; } from "../axes";
import { CirclesWithG } from ".";
import { generateRandomDataset } from "../helpers";
import { TextsWithG } from "../texts"; import { TextsWithG } from "../texts";
import { Circles } from "./Circles"; import { Circles } from "./Circles";
......
import React, { useRef, useState } from "react";
import { Button, Comment } from "../commons";
import { generateDataset, generateRandomDataset } from "../helpers";
import { useSize } from "../hooks";
import { ChartV0 } from "./ChartV0";
import { ScatterChart } from "./ScatterChart";
export const ScatterExamples = () => {
const [dataset, setDataset] = useState(generateRandomDataset(20, 200));
const target = useRef(null);
const size = useSize(target);
const handleClick = () => {
setDataset(generateDataset());
};
// console.log("dataset", dataset);
return (
<div>
<h1>Scatter Chart Examples</h1>
<Button className="mr-4" onClick={handleClick}>
새로운 무작위 데이터로 차트를 갱신하려면 클릭하세요.
</Button>
<Comment>고정된 데이터에 대해서 scatter plot. 이전 축 적용</Comment>
<ChartV0 />
<Comment>resizable이 적용된 scatter plot. 새로운 축 적용.</Comment>
<div ref={target}>
<ScatterChart dataset={dataset} dimensions={size} />
</div>
</div>
);
};
export { CirclesWithD3 } from "./CirclesWithD3";
export { CirclesWithG } from "./CirclesWithG"; export { CirclesWithG } from "./CirclesWithG";
export { CirclesWithSvg } from "./CirclesWithSvg";
export { ScatterExamples } from "./ScatterExamples";
import React from "react";
import { ScaleLinear, ScaleBand } from "d3-scale";
type Props = {
dataset: number[];
height: number;
xScale: ScaleBand<number>;
yScale: ScaleLinear<number, number>;
};
export const BarText = ({ dataset, height, xScale, yScale }: Props) => {
return (
<g fontSize={"15px"} textAnchor="middle" fill="white">
{dataset.map((d, i) => (
<text
key={i}
x={(xScale(i) ?? 0) + xScale.bandwidth() / 2}
y={height - yScale(d) + 14}
>
{d}
</text>
))}
</g>
);
};
import { ScaleLinear, format } from "d3";
import React from "react";
type Props = {
dataset: number[][];
xScale: ScaleLinear<number, number>;
yScale: ScaleLinear<number, number>;
};
export const TextsWithG = ({ dataset, xScale, yScale }: Props) => {
// console.log("dataset in texts with g", dataset);
// const asPercentage = format(".1%");
const toFixed = format(".1f");
return (
<g fontSize={"10px"}>
{dataset.map((d) => (
<text key={d[0]} x={xScale(d[0])} y={yScale(d[1])}>{`${toFixed(
d[0]
)}, ${toFixed(d[1])}`}</text>
))}
</g>
);
};
export { TextsWithG } from "./TextsWithG";
export { BarText } from "./BarText";
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment