修复温度走势图不显示:移除 IntersectionObserver 延迟渲染
问题:图表只在 IntersectionObserver 检测到视口交叉后才渲染 - 卡片折叠时图表区域永远不可见,IntersectionObserver 不触发 - 小屏幕/快速滚动时图表可能来不及渲染 修复: - 移除 IntersectionObserver 懒加载逻辑 - 图表始终立即渲染(useChart 在挂载时初始化) - Chart.js animation:false 确保快速渲染,无性能代价 - 清理未使用的 useState/useEffect 导入
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { ChartConfiguration } from "chart.js";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useMemo, useRef } from "react";
|
||||
import { BarChart3 } from "lucide-react";
|
||||
import type { CityDetail } from "@/lib/dashboard-types";
|
||||
import { useChart } from "@/hooks/useChart";
|
||||
@@ -64,15 +64,14 @@ function buildTemperatureChartSignature(detail: CityDetail) {
|
||||
export function AiCityTemperatureChart({ detail }: { detail: CityDetail }) {
|
||||
const { locale } = useI18n();
|
||||
const sectionRef = useRef<HTMLElement | null>(null);
|
||||
const [shouldRenderChart, setShouldRenderChart] = useState(false);
|
||||
const cityKey = `${detail.name || detail.display_name || ""}:${detail.local_date || ""}`;
|
||||
const chartSignature = useMemo(
|
||||
() => (shouldRenderChart ? buildTemperatureChartSignature(detail) : ""),
|
||||
[detail, shouldRenderChart],
|
||||
() => buildTemperatureChartSignature(detail),
|
||||
[detail],
|
||||
);
|
||||
const computedChartData = useMemo(
|
||||
() => (shouldRenderChart ? getTemperatureChartData(detail, locale) : null),
|
||||
[chartSignature, detail, locale, shouldRenderChart],
|
||||
() => getTemperatureChartData(detail, locale),
|
||||
[chartSignature, detail, locale],
|
||||
);
|
||||
const lastChartDataRef = useRef<{
|
||||
cityKey: string;
|
||||
@@ -233,26 +232,6 @@ export function AiCityTemperatureChart({ detail }: { detail: CityDetail }) {
|
||||
observationLabel,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldRenderChart) return;
|
||||
if (typeof window === "undefined" || !("IntersectionObserver" in window)) {
|
||||
setShouldRenderChart(true);
|
||||
return;
|
||||
}
|
||||
const target = sectionRef.current;
|
||||
if (!target) return;
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (!entries.some((entry) => entry.isIntersecting)) return;
|
||||
setShouldRenderChart(true);
|
||||
observer.disconnect();
|
||||
},
|
||||
{ rootMargin: "220px 0px" },
|
||||
);
|
||||
observer.observe(target);
|
||||
return () => observer.disconnect();
|
||||
}, [shouldRenderChart]);
|
||||
|
||||
return (
|
||||
<section className="scan-ai-city-section chart" ref={sectionRef}>
|
||||
<div className="scan-ai-city-section-title">
|
||||
@@ -260,13 +239,7 @@ export function AiCityTemperatureChart({ detail }: { detail: CityDetail }) {
|
||||
<span>{locale === "en-US" ? "Evidence · intraday path" : "证据 · 今日日内路径"}</span>
|
||||
</div>
|
||||
<div className="scan-ai-city-chart">
|
||||
{shouldRenderChart ? (
|
||||
<canvas ref={canvasRef} />
|
||||
) : (
|
||||
<div className="scan-ai-city-chart-placeholder">
|
||||
{locale === "en-US" ? "Chart will render when visible" : "图表进入视口后再渲染"}
|
||||
</div>
|
||||
)}
|
||||
<canvas ref={canvasRef} />
|
||||
</div>
|
||||
{chartData ? (
|
||||
<div className="scan-ai-city-chart-legend">
|
||||
|
||||
Reference in New Issue
Block a user