自定义hook:useHistoryChart
完整的hook代码
import { createChart } from "lightweight-charts";
let chart;
let lineSeriesYes;
let lineSeriesNo;
// chart,lineSeriesYes,lineSeriesNo
const useHistoryChart = (
historyPrice,
isMobile,
activeIndex,
setActiveIndex,
chartContainerRef,
chartDataYes,
setChartDataYes,
chartDataNo,
setChartDataNo
) => {
//历史图表
const [isTimeScaleActive, setIsTimeScaleActive] = useState(false);
const [chartHeight, setChartHeight] = useState(370);
useEffect(() => {
// 首先要确保表格数据拿到 再去生成 不然会报undefined的错
if (historyPrice && chartDataYes && chartDataNo) {
// 如果表格没有生成才进入这个if判断 生成表格
if (chartContainerRef.current) {
if ((chartContainerRef.current as HTMLElement).childNodes.length == 0) {
chart = createChart(chartContainerRef.current, {
width: isMobile ? 366 : 900,
height: chartHeight,
handleScale: {
mouseWheel: false,
axisPressedMouseMove: false,
},
handleScroll: {
pressedMouseMove: false,
vertTouchDrag: false,
},
leftPriceScale: {
borderVisible: false,
},
rightPriceScale: {
visible: true,
borderVisible: false,
},
timeScale: {
borderVisible: false,
timeVisible: true,
tickMarkFormatter: (time, tickMarkType) => {
const activeTimeScale = activeIndex;
console.log("activeTimeScale", activeTimeScale);
console.log("tickMarkType", tickMarkType);
const date1 = new Date(time * 1000).toLocaleString("en-US", {
hour: "numeric",
minute: "numeric",
hour12: true,
});
const date2 = new Date(time * 1000).toLocaleString("en-US", {
month: "short",
day: "numeric",
hour12: true,
});
if (
activeTimeScale == 0 ||
activeTimeScale == 1 ||
activeTimeScale == 2
) {
return date1;
} else {
return date2;
}
},
},
localization: {
priceFormatter: (price) => {
return "$" + price.toFixed(2);
},
timeFormatter: (time) => {
const date = new Date(time * 1000).toLocaleString("en-US", {
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "numeric",
hour12: true,
});
return date;
},
},
layout: {
fontFamily: "Heebo,sans-serif",
textColor: "#fff",
background: {
color: "#0e1520",
},
},
grid: {
vertLines: {
visible: false,
},
horzLines: {
visible: false,
},
},
});
lineSeriesYes = chart?.addLineSeries({
color: "#FF6933",
});
lineSeriesNo = chart?.addLineSeries({
color: "#FF6933",
});
}
}
// 拿到数据后要做排成升序 才能传入setData
const sortChartDataYes = chartDataYes?.sort((a, b) => a.time - b.time);
lineSeriesYes?.setData(sortChartDataYes);
let sortChartDataNo = chartDataNo?.sort((a, b) => a.time - b.time);
lineSeriesNo?.setData(sortChartDataNo);
chart?.applyOptions({
timeScale: {
// 时间提示 就是鼠标在表格线上滑动会展示对应的时间戳
tickMarkFormatter: (time) => {
const activeTimeScale = activeIndex;
const date1 = new Date(time * 1000).toLocaleString("en-US", {
second: "numeric",
minute: "numeric",
hour: "numeric",
hour12: true,
});
const date2 = new Date(time * 1000).toLocaleString("en-US", {
hour: "numeric",
minute: "numeric",
hour12: true,
});
const date3 = new Date(time * 1000).toLocaleString("en-US", {
month: "short",
weekday: "short",
// hour12: true,
});
const date4 = new Date(time * 1000).toLocaleString("en-US", {
month: "short",
day: "numeric",
// hour12: true,
});
if (activeTimeScale == 0) {
return date1;
} else if (activeTimeScale == 1 || activeTimeScale == 2) {
return date2;
} else if (activeTimeScale == 3) {
return date3;
} else {
return date4;
}
},
},
});
// left top title
var toolTip = document.createElement("div");
toolTip.className = "leftTopTitle";
toolTip.id = "tooltip-id";
(chartContainerRef.current as HTMLDivElement).appendChild(toolTip);
toolTip.style.display = "block";
toolTip.style.fontWeight = "500";
toolTip.style.position = "absolute";
toolTip.style.left = 20 + "px";
toolTip.style.top = "-" + 8 + "px";
toolTip.style.zIndex = "10";
// get the title of the chart
const setToolTip = () => {
toolTip.innerHTML =
`<div style="font-size: 16px; margin: 4px 0px; color:#FFF;">
YES
</div>` +
`<div style="font-size: 22px; margin: 4px 0px; color:#FFF" >` +
0.5 +
"$" +
"</div>";
};
setToolTip();
//update the title base on the mousemove
chart?.subscribeCrosshairMove(function (param) {
if (
param === undefined ||
param.time === undefined ||
param.point.x < 0 ||
param.point.x > 900 ||
param.point.y < 0 ||
param.point.y > 390
) {
setToolTip();
} else {
const seriesData = param.seriesData;
if (seriesData && seriesData.size > 0) {
// Get the first entry
const firstEntry = seriesData.values().next().value;
if (firstEntry) {
const yesValue = `${firstEntry.value}$`;
console.log("yesValue", yesValue);
toolTip.innerHTML =
`<div style="font-size: 16px; margin: 4px 0px; color:#FFF;">
YES
</div>` +
`<div style="font-size: 22px; margin: 4px 0px; color:#FFF" >` +
yesValue +
"</div>";
}
}
}
});
chart?.timeScale().fitContent();
}
}, [chartDataYes, chartDataNo, isTimeScaleActive, activeIndex]);
function updateYesLine(chartDataYes, index = 0) {
chartDataYes?.sort((a, b) => a.time - b.time);
setChartDataYes(chartDataYes);
}
function updateNoLine(chartDataNo, index = 0) {
// console.log("")
chartDataNo?.sort((a, b) => a.time - b.time);
setChartDataNo(chartDataNo);
}
// 点击时间范围的按钮会调用这个函数
function handleChangeTimeScale(index) {
console.log("handleChangeTimeScale index", index);
if (activeIndex == index) {
return;
}
setActiveIndex(index);
setIsTimeScaleActive(true);
updateYesLine(historyPrice[index]["price_list"]["option0"], index);
updateNoLine(historyPrice[index]["price_list"]["option1"], index);
}
return { updateYesLine, updateNoLine, handleChangeTimeScale };
};
export default useHistoryChart;
使用hook
点击切换时间范围的时候数据没有对应更新 刚进来的时候表格没有生成 是因为chartDataYes没有值,所以chartDataYes变量要定义在hook的外面,从接口拿到数据就setchartDataYes
interface ChartData {
time: number;
value: number;
}
const [chartDataYes, setChartDataYes] = useState<ChartData[]>();
const [chartDataNo, setChartDataNo] = useState<ChartData[]>();
const chartContainerRef = useRef();
const { handleChangeTimeScale} =useHistoryChart(historyPrice, isMobile, activeIndex,setActiveIndex,chartContainerRef,chartDataYes, setChartDataYes,chartDataNo, setChartDataNo)
html
{/* 表格 */}
<Box
width={{
xs: "360px",
sm: "500px",
md: "700px",
lg: "1000px",
}}
>
<div
className={styles.tableContainer}
id="tableContainer"
style={{ width: "100%" }}
>
<div
ref={chartContainerRef}
id="test-id"
style={{ position: "relative" }}
/>
</div>
</Box>
<hr className={styles.horizontalLine} />
{/* 时间范围筛选按钮 */}
<ButtonGroup
variant="text"
aria-label="text button group"
className={styles.timeScaleBar}
>
<Button
className={`${
activeIndex == 0 ? styles.activeTimeScale : ""
} ${styles.timeScaleBtn}`}
// focusable="false"
// quaternary
// size="small"
onClick={() => handleChangeTimeScale(0)}
>
1H
</Button>
<Button
className={`${
activeIndex == 1 ? styles.activeTimeScale : ""
} ${styles.timeScaleBtn}`}
onClick={() => handleChangeTimeScale(1)}
>
6H
</Button>
<Button
className={`${
activeIndex == 2 ? styles.activeTimeScale : ""
} ${styles.timeScaleBtn}`}
onClick={() => handleChangeTimeScale(2)}
>
1D
</Button>
<Button
className={`${
activeIndex == 3 ? styles.activeTimeScale : ""
} ${styles.timeScaleBtn}`}
onClick={() => handleChangeTimeScale(3)}
>
1W
</Button>
<Button
className={`${
activeIndex == 4 ? styles.activeTimeScale : ""
} ${styles.timeScaleBtn}`}
onClick={() => handleChangeTimeScale(4)}
>
1M
</Button>
<Button
className={`${
activeIndex == 5 ? styles.activeTimeScale : ""
} ${styles.timeScaleBtn}`}
onClick={() => handleChangeTimeScale(5)}
>
ALL
</Button>
</ButtonGroup>
点击时间范围后生成 然后再点击就不会切换线了 是因为变量的定义位置 lineSeriesYes会变成undefined 改变变量定义的位置即可,要定义在hook文件
let chart;
let lineSeriesYes;
let lineSeriesNo;
// chart,lineSeriesYes,lineSeriesNo
const useHistoryChart = (
historyPrice,
isMobile,
。。。