wykrestest
Version:
Candlestick Chart made with Konva, React and Jotai
61 lines (60 loc) • 3 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import React, { useState, useEffect, useRef, useLayoutEffect } from 'react';
import { Layer, Group } from 'react-konva';
import { Border } from '../utils/Border';
import { Rect, Line } from 'react-konva';
import { checkBoundry } from '../utils/utils';
import { useAtomValue, useAtom } from 'jotai';
import { dragAtom, dimsAtom, gapAtom, maxXAtom, dataAtom } from '../store';
import { xAtom, yAtom, scaleXAtom, scaleYAtom, dataHLAtom } from '../store';
export const Main = () => {
const layerRef = useRef(null);
const groupRef = useRef(null);
const [x, setX] = useAtom(xAtom);
const y = useAtomValue(yAtom);
const scaleX = useAtomValue(scaleXAtom);
const scaleY = useAtomValue(scaleYAtom);
const dims = useAtomValue(dimsAtom);
const maxX = useAtomValue(maxXAtom);
const data = useAtomValue(dataAtom);
const dragBound = (pos) => {
const newPos = checkBoundry(pos, maxX);
setX(newPos.x);
return { x: newPos.x, y: y };
};
const drag = useAtomValue(dragAtom);
useLayoutEffect(() => {
if (drag) {
groupRef.current.startDrag();
groupRef.current.cache({ pixelRatio: .9 });
}
else {
groupRef.current.stopDrag();
groupRef.current.clearCache();
}
}, [drag]);
return (_jsx(_Fragment, { children: _jsxs(Layer, { ref: layerRef, clip: { x: 0, y: 0, height: dims.height, width: dims.widthSub }, children: [_jsx(Group, { ref: groupRef, x: x, y: y, scaleX: scaleX, scaleY: scaleY, dragBoundFunc: dragBound, children: data.map((item, i) => _jsx(CandleMemo, { item: item, i: i }, item.api_date)) }), _jsx(Border, { dims: dims })] }) }));
};
export const MainMemo = React.memo(Main);
//the mapped items
export const Candle = ({ item, i }) => {
const gap = useAtomValue(gapAtom);
const [openPx, setOpenPx] = useState(0);
const [closePx, setClosePx] = useState(0);
const [highPx, setHighPx] = useState(0);
const [lowPx, setLowPx] = useState(0);
const [fill, setFill] = useState('black');
const dataHL = useAtomValue(dataHLAtom);
const dims = useAtomValue(dimsAtom);
useEffect(() => {
if (item.open != 0 && dataHL.high != 0) {
setFill(item.open > item.close ? 'red' : 'green');
setOpenPx(((dataHL.high - item.open) / dataHL.diff) * dims.heightSub);
setClosePx(((dataHL.high - item.close) / dataHL.diff) * dims.heightSub);
setHighPx(((dataHL.high - item.high) / dataHL.diff) * dims.heightSub);
setLowPx(((dataHL.high - item.low) / dataHL.diff) * dims.heightSub);
}
}, [dataHL, item]);
return (_jsxs(_Fragment, { children: [_jsx(Rect, { x: i * gap, y: openPx, width: gap, height: closePx - openPx, fill: fill }), _jsx(Line, { x: i * gap, points: [2, highPx, 2, lowPx], stroke: fill, strokeWidth: 1 })] }));
};
export const CandleMemo = React.memo(Candle);