- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- rtk
- websocket
- Firebase
- 주식차트
- nestjs
- 차트
- nextjs
- 에러
- 항해99
- javascript
- 비전공자
- error
- 주식
- 차트만들기
- 차트구현
- 리액트
- 3주차
- apollo
- react
- 채팅
- typescript
- API
- Redux
- chart
- Flutter
- Coin
- 코인
- graphql
- 코인차트
- typeorm
Act99 기술블로그
[React] 직접 주가 캔들 차트 & 거래량 바 차트 만들기2 (라이브러리 x) (SVG 연습용) 본문
이번에는 캔들 차트를 만들 차례이다.
기본틀은 거래량 차트 만들기와 같으며,
캔들차트 구현이라는 점에서 다르다.
https://bugerstory.tistory.com/32
해야 할 일
1. 데이터 불러오기
2. 금액 최소값과 최대값을 구한 후, 7개의 구분선으로 나누기.
3. 시가와 종가 데이터로 바 차트 구현하기
4. 고가와 저가 데이터로 얇은 바 차트 구현하기
5. 시가&종가 바와 고가&저가 바를 합쳐서 캔들차트 구현하기
이다.
먼저 해야할 일 1, 2, 3 을 작업했다.
저번 시간에 했던 거래량 바 차트 만들기와 유사하다.
다른 점은 바의 최저점이 0이 아니라 시가 또는 종가라는 점이다.
const CandleChart: React.FC<CandleStickProps> = ({
date,
open,
close,
high,
low,
name,
}) => {
const x0 = 150;
const xAxisLength = SVG_CHART_WIDTH - x0 * 2;
const y0 = 50;
const yAxisLength = SVG_CHART_HEIGHT - y0 * 2;
const xAxisY = y0 + yAxisLength;
const dataArray: [string, number, number, number, number][] = [];
for (let i = 0; i < date.length; i++) {
dataArray.push([date[i], open[i], close[i], high[i], low[i]]);
}
console.log(dataArray);
const dataYMax = dataArray.reduce(
(max, [_, open, close, high, low]) => Math.max(max, high),
-Infinity
);
console.log(dataYMax);
const dataYMin = dataArray.reduce(
(min, [_, open, close, high, low]) => Math.min(min, low),
+Infinity
);
console.log(dataYMin);
const dataYRange = dataYMax - dataYMin;
const numYTicks = 7;
const barPlothWidth = xAxisLength / dataArray.length;
return (
<div>
<svg width={SVG_CHART_WIDTH} height={SVG_CHART_HEIGHT}>
<line x1={x0} y1={xAxisY} x2={x0 + xAxisLength} y2={xAxisY} />
<text x={SVG_CHART_WIDTH - x0} y={xAxisY + 10}>
{name[name.length - 1]}
</text>
{/* 가로선 작성(css name => lineLight) */}
{Array.from({ length: numYTicks }).map((_, index) => {
const y = y0 + index * (yAxisLength / numYTicks);
const yValue = Math.round(
dataYMax - index * (dataYRange / numYTicks)
);
return (
<g key={index}>
<line
className="lineLight"
x1={SVG_CHART_WIDTH - x0}
x2={x0}
y1={y}
y2={y}
></line>
<text x={x0 + xAxisLength + 80} y={y + 5} textAnchor="end">
{yValue.toLocaleString()} ₩
</text>
</g>
);
})}
{dataArray.map(([day, open, close, high, low], index) => {
const openAndClose = [];
openAndClose.push([open, close]);
// console.log(open > close ? 1 : 2);
console.log(open);
console.log(close);
console.log(openAndClose);
const x = x0 + index * barPlothWidth;
const sidePadding = 5;
let yRatio = 0;
const yRatioGenerator = () => {};
return (
<g key={index}>
<rect
fill={open > close ? "green" : "red"}
x={x + sidePadding / 2}
y={
open > close
? (SVG_CHART_HEIGHT * ((open + close) / 2)) / dataYMax
: (SVG_CHART_HEIGHT * ((close + open) / 2)) / dataYMax
}
width={barPlothWidth - sidePadding}
height={
open > close
? (SVG_CHART_HEIGHT * (open - close)) / dataYMax
: (SVG_CHART_HEIGHT * (close - open)) / dataYMax
}
></rect>
</g>
);
})}
<line
x1={SVG_VOLUME_WIDTH - x0}
y1={y0}
x2={x0 + xAxisLength}
y2={y0 + yAxisLength}
/>
</svg>
</div>
);
};
그리고 실행해 본 결과..
차트가 뒤집혀 있는 것을 볼 수 있다. (차트 구현도 제대로 되지 않고 있는 것을 알 수 있다.)
그 이유는.....
svg의 y축은 아래로 그 값이 형성되는데, 이를 계산하지 않았기 때문이다.
(말로 설명이 어렵지만 쉽게 말해서 뒤집어주어야 한다.)
간략하게 말해서 애초부터 계획을 잘못 짠 것이었다... ㅎ.ㅎ
수정한 결과
let yRatio = 0;
const yRatioGenerator = (open: number, close: number) => {
if (open > close) {
yRatio = (open - dataYMin) / dataYRange;
if (yRatio > 0) {
return yRatio;
} else return (yRatio = open / dataYRange / 2);
} else {
yRatio = (close - dataYMin) / dataYRange;
if (yRatio > 0) {
return yRatio;
} else return (yRatio = open / dataYRange / 2);
}
};
let yHighRatio = 0;
const yHighRatioGenerator = (high: number) => {
yHighRatio = (high - dataYMin) / dataYRange;
if (yHighRatio > 0) {
return yHighRatio;
} else return (yRatio = high / dataYRange / 2);
};
const yOpenClose =
y0 + (1 - yRatioGenerator(open, close)) * yAxisLength;
const yHighLow = y0 + (1 - yHighRatioGenerator(high)) * yAxisLength;
얼핏보면 차트가 잘 구현된 것으로 보일 수 있으나
아직 제대로 구현이 되고 있지 않았다.
그 이유는 "시가 종가의 y 축의 scale 값 대비 y 축 시작점" 과 "고가 저가의 y축 scale 값 대비 y 축 시작점" 에서 미스가 났기 때문이다.
따라서 이를 구현하기 위해서 모든 데이터를 종합한 캔들스틱 컴퍼넌트를 직접 구현한 후, 차트상에 올리는 작업을 실시해야하며, 아예 다 갈아엎어야한다.
지금 바로 갈아엎기 작업을 실행하러 갈 예정이다.
'개발팁저장소 > react' 카테고리의 다른 글
[React] 직접 주가 캔들 차트 & 거래량 바 차트 만들기4 - onWheel 을 통해 데이터값을 추가시키거나 감소시키기 (라이브러리 x) (SVG 연습용) (0) | 2021.12.01 |
---|---|
[React] 직접 주가 캔들 차트 & 거래량 바 차트 만들기3 (라이브러리 x) (SVG 연습용) (0) | 2021.11.30 |
[React] 직접 주가 캔들 차트 & 거래량 바 차트 만들기 (라이브러리 x) (SVG 연습용) (0) | 2021.11.27 |
[React] 주식사이트 만들기 / React Google Chart 사용 (1) | 2021.11.26 |
Yarn 이 먹히지 않을 때! yarn install | yarn remove 가 먹히지 않을 때 (0) | 2021.11.24 |