I referred to this example on CodePen using react-financial-charts library, specifically attached here: https://codesandbox.io/p/sandbox/react-financial-charts-demo-forked-zw4o4?file=%2Findex.js. However, when I re-coded it using Vite.js and ran the file, the chart mostly displayed like the CodePen demo, except for the hover effect as shown in the example. Where did I go wrong?
My code here
App.jsx
import React from "react";
import ReactDOM from "react-dom";
import { format } from "d3-format";
import { timeFormat } from "d3-time-format";
import {
elderRay,
ema,
discontinuousTimeScaleProviderBuilder,
Chart,
ChartCanvas,
CurrentCoordinate,
BarSeries,
CandlestickSeries,
ElderRaySeries,
LineSeries,
MovingAverageTooltip,
OHLCTooltip,
SingleValueTooltip,
lastVisibleItemBasedZoomAnchor,
XAxis,
YAxis,
CrossHairCursor,
EdgeIndicator,
MouseCoordinateX,
MouseCoordinateY,
ZoomButtons,
withDeviceRatio,
withSize
} from "react-financial-charts";
import { initialData } from "./data.jsx";
// import ChartExample from "./Chart.jsx";
const rotateArray2 = function (nums, k) {
// reverse helper function
function reverse(arr, start, end) {
while (start < end) {
[arr[start], arr[end]] = [arr[end], arr[start]];
start++;
end--;
}
}
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
return nums;
};
const App = () => {
const ScaleProvider = discontinuousTimeScaleProviderBuilder().inputDateAccessor(
(d) => new Date(d.date)
);
const height = 700;
const width = 900;
const margin = { left: 0, right: 48, top: 0, bottom: 24 };
const ema12 = ema()
.id(1)
.options({ windowSize: 12 })
.merge((d, c) => {
d.ema12 = c;
})
.accessor((d) => d.ema12);
const ema26 = ema()
.id(2)
.options({ windowSize: 26 })
.merge((d, c) => {
d.ema26 = c;
})
.accessor((d) => d.ema26);
const elder = elderRay();
const rotateArray2 = function (nums, k) {
// reverse helper function
function reverse(arr, start, end) {
while (start < end) {
[arr[start], arr[end]] = [arr[end], arr[start]];
start++;
end--;
}
}
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
return nums;
};
const calculatedData = elder(ema26(ema12(rotateArray2(initialData))));
const { data, xScale, xAccessor, displayXAccessor } = ScaleProvider(
rotateArray2(initialData)
);
const pricesDisplayFormat = format(".2f");
const max = xAccessor(data[data.length - 1]);
const min = xAccessor(data[Math.max(0, 0)]);
const xExtents = [min, max + 5];
const gridHeight = height - margin.top - margin.bottom;
const elderRayHeight = 100;
const elderRayOrigin = (_, h) => [0, h - elderRayHeight];
const barChartHeight = gridHeight / 4;
const barChartOrigin = (_, h) => [0, h - barChartHeight - elderRayHeight];
const chartHeight = gridHeight - elderRayHeight;
const yExtents = (data) => {
return [data.high, data.low];
};
const dateTimeFormat = "%d %b";
const timeDisplayFormat = timeFormat(dateTimeFormat);
const barChartExtents = (data) => {
return data.volume;
};
const candleChartExtents = (data) => {
return [data.high, data.low];
};
const yEdgeIndicator = (data) => {
return data.close;
};
const volumeColor = (data) => {
return data.close > data.open
? "rgba(38, 166, 154, 0.3)"
: "rgba(239, 83, 80, 0.3)";
};
const volumeSeries = (data) => {
return data.volume;
};
const openCloseColor = (data) => {
return data.close > data.open ? "#26a69a" : "#ef5350";
};
return (
<ChartCanvas
height={height}
ratio={3}
width={width}
margin={margin}
data={data}
displayXAccessor={displayXAccessor}
seriesName="Data"
xScale={xScale}
xAccessor={xAccessor}
xExtents={xExtents}
zoomAnchor={lastVisibleItemBasedZoomAnchor}
>
<Chart
id={2}
height={barChartHeight}
origin={barChartOrigin}
yExtents={barChartExtents}
>
<BarSeries fillStyle={volumeColor} yAccessor={volumeSeries} />
</Chart>
<Chart id={3} height={chartHeight} yExtents={candleChartExtents}>
<XAxis showGridLines showTickLabel={false} />
<YAxis showGridLines tickFormat={pricesDisplayFormat} />
<CandlestickSeries />
<LineSeries yAccessor={ema26.accessor()} strokeStyle={ema26.stroke()} />
<CurrentCoordinate
yAccessor={ema26.accessor()}
fillStyle={ema26.stroke()}
/>
<LineSeries yAccessor={ema12.accessor()} strokeStyle={ema12.stroke()} />
<CurrentCoordinate
yAccessor={ema12.accessor()}
fillStyle={ema12.stroke()}
/>
<MouseCoordinateY
rectWidth={margin.right}
displayFormat={pricesDisplayFormat}
/>
<EdgeIndicator
itemType="last"
rectWidth={margin.right}
fill={openCloseColor}
lineStroke={openCloseColor}
displayFormat={pricesDisplayFormat}
yAccessor={yEdgeIndicator}
/>
<MovingAverageTooltip
origin={[8, 24]}
options={[
{
yAccessor: ema26.accessor(),
type: "EMA",
stroke: ema26.stroke(),
windowSize: ema26.options().windowSize
},
{
yAccessor: ema12.accessor(),
type: "EMA",
stroke: ema12.stroke(),
windowSize: ema12.options().windowSize
}
]}
/>
<ZoomButtons />
<OHLCTooltip origin={[8, 16]} />
</Chart>
<Chart
id={4}
height={elderRayHeight}
yExtents={[0, elder.accessor()]}
origin={elderRayOrigin}
padding={{ top: 8, bottom: 8 }}
>
<XAxis showGridLines gridLinesStrokeStyle="#e0e3eb" />
<YAxis ticks={4} tickFormat={pricesDisplayFormat} />
<MouseCoordinateX displayFormat={timeDisplayFormat} />
<MouseCoordinateY
rectWidth={margin.right}
displayFormat={pricesDisplayFormat}
/>
<ElderRaySeries yAccessor={elder.accessor()} />
<SingleValueTooltip
yAccessor={elder.accessor()}
yLabel="Elder Ray"
yDisplayFormat={(d) =>
`${pricesDisplayFormat(d.bullPower)}, ${pricesDisplayFormat(
d.bearPower
)}`
}
origin={[8, 16]}
/>
</Chart>
<CrossHairCursor />
</ChartCanvas>
);
};
export default App;
main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
)
data.jsx I follow by example in codepen I show before
I want to debug and fix the chart more friendly and beautifully