feat: y轴坐标改为左侧展示

This commit is contained in:
hzm
2026-02-24 21:36:56 +08:00
parent b9ee4546b7
commit 194f9246ef
2 changed files with 84 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import { useMemo } from 'react'; import { useMemo, useRef, useEffect } from 'react';
import { import {
Chart as ChartJS, Chart as ChartJS,
CategoryScale, CategoryScale,
@@ -27,6 +27,9 @@ ChartJS.register(
* referenceNav: 参考净值(最新单位净值),用于计算涨跌幅;未传则用当日第一个估值作为参考。 * referenceNav: 参考净值(最新单位净值),用于计算涨跌幅;未传则用当日第一个估值作为参考。
*/ */
export default function FundIntradayChart({ series = [], referenceNav }) { export default function FundIntradayChart({ series = [], referenceNav }) {
const chartRef = useRef(null);
const hoverTimeoutRef = useRef(null);
const chartData = useMemo(() => { const chartData = useMemo(() => {
if (!series.length) return { labels: [], datasets: [] }; if (!series.length) return { labels: [], datasets: [] };
const labels = series.map((d) => d.time); const labels = series.map((d) => d.time);
@@ -91,7 +94,7 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
}, },
y: { y: {
display: true, display: true,
position: 'right', position: 'left',
grid: { color: '#1f2937', drawBorder: false }, grid: { color: '#1f2937', drawBorder: false },
ticks: { ticks: {
color: '#9ca3af', color: '#9ca3af',
@@ -100,11 +103,45 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
} }
} }
}, },
onHover: (event, chartElement) => { onHover: (event, chartElement, chart) => {
event.native.target.style.cursor = chartElement[0] ? 'crosshair' : 'default'; const target = event?.native?.target;
if (target) {
target.style.cursor = chartElement[0] ? 'crosshair' : 'default';
}
const currentChart = chart || chartRef.current;
if (!currentChart) return;
if (hoverTimeoutRef.current) {
clearTimeout(hoverTimeoutRef.current);
hoverTimeoutRef.current = null;
}
if (chartElement[0]) {
hoverTimeoutRef.current = setTimeout(() => {
const c = chartRef.current || currentChart;
if (!c) return;
c.setActiveElements([]);
if (c.tooltip) {
c.tooltip.setActiveElements([], { x: 0, y: 0 });
}
c.update();
if (target) {
target.style.cursor = 'default';
}
}, 2000);
}
} }
}), []); }), []);
useEffect(() => {
return () => {
if (hoverTimeoutRef.current) {
clearTimeout(hoverTimeoutRef.current);
}
};
}, []);
const plugins = useMemo(() => [{ const plugins = useMemo(() => [{
id: 'crosshair', id: 'crosshair',
afterDraw: (chart) => { afterDraw: (chart) => {
@@ -157,9 +194,9 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
const valueStr = typeof val === 'number' ? `${val >= 0 ? '+' : ''}${val.toFixed(2)}%` : String(val); const valueStr = typeof val === 'number' ? `${val >= 0 ? '+' : ''}${val.toFixed(2)}%` : String(val);
const vw = ctx.measureText(valueStr).width + 8; const vw = ctx.measureText(valueStr).width + 8;
ctx.fillStyle = prim; ctx.fillStyle = prim;
ctx.fillRect(rightX - vw, y - 8, vw, 16); ctx.fillRect(leftX, y - 8, vw, 16);
ctx.fillStyle = bgText; ctx.fillStyle = bgText;
ctx.fillText(valueStr, rightX - vw / 2, y); ctx.fillText(valueStr, leftX + vw / 2, y);
} }
ctx.restore(); ctx.restore();
} }
@@ -191,7 +228,7 @@ export default function FundIntradayChart({ series = [], referenceNav }) {
{displayDate && <span style={{ fontSize: 11 }}>估值日期 {displayDate}</span>} {displayDate && <span style={{ fontSize: 11 }}>估值日期 {displayDate}</span>}
</div> </div>
<div style={{ position: 'relative', height: 100, width: '100%' }}> <div style={{ position: 'relative', height: 100, width: '100%' }}>
<Line data={chartData} options={options} plugins={plugins} /> <Line ref={chartRef} data={chartData} options={options} plugins={plugins} />
</div> </div>
</div> </div>
); );

View File

@@ -35,6 +35,7 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const chartRef = useRef(null); const chartRef = useRef(null);
const hoverTimeoutRef = useRef(null);
useEffect(() => { useEffect(() => {
// If collapsed, don't fetch data unless we have no data yet // If collapsed, don't fetch data unless we have no data yet
@@ -198,7 +199,7 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
}, },
y: { y: {
display: true, display: true,
position: 'right', position: 'left',
grid: { grid: {
color: '#1f2937', color: '#1f2937',
drawBorder: false, drawBorder: false,
@@ -217,8 +218,42 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
mode: 'index', mode: 'index',
intersect: false, intersect: false,
}, },
onHover: (event, chartElement) => { onHover: (event, chartElement, chart) => {
event.native.target.style.cursor = chartElement[0] ? 'crosshair' : 'default'; const target = event?.native?.target;
if (target) {
target.style.cursor = chartElement[0] ? 'crosshair' : 'default';
}
const currentChart = chart || chartRef.current;
if (!currentChart) return;
if (hoverTimeoutRef.current) {
clearTimeout(hoverTimeoutRef.current);
hoverTimeoutRef.current = null;
}
if (chartElement[0]) {
hoverTimeoutRef.current = setTimeout(() => {
const c = chartRef.current || currentChart;
if (!c) return;
c.setActiveElements([]);
if (c.tooltip) {
c.tooltip.setActiveElements([], { x: 0, y: 0 });
}
c.update();
if (target) {
target.style.cursor = 'default';
}
}, 2000);
}
}
};
}, []);
useEffect(() => {
return () => {
if (hoverTimeoutRef.current) {
clearTimeout(hoverTimeoutRef.current);
} }
}; };
}, []); }, []);
@@ -360,10 +395,10 @@ export default function FundTrendChart({ code, isExpanded, onToggleExpand, trans
const valueStr = (typeof value === 'number' ? value.toFixed(2) : value) + '%'; const valueStr = (typeof value === 'number' ? value.toFixed(2) : value) + '%';
const valWidth = ctx.measureText(valueStr).width + 8; const valWidth = ctx.measureText(valueStr).width + 8;
ctx.fillStyle = primaryColor; ctx.fillStyle = primaryColor;
ctx.fillRect(rightX - valWidth, y - 8, valWidth, 16); ctx.fillRect(leftX, y - 8, valWidth, 16);
ctx.fillStyle = '#0f172a'; // --background ctx.fillStyle = '#0f172a'; // --background
ctx.textAlign = 'center'; ctx.textAlign = 'center';
ctx.fillText(valueStr, rightX - valWidth / 2, y); ctx.fillText(valueStr, leftX + valWidth / 2, y);
} }
} }