Delay background preload until map interaction stops

This commit is contained in:
2569718930@qq.com
2026-04-12 10:44:03 +08:00
parent 627bb8aa06
commit a0adf05d1e
3 changed files with 51 additions and 2 deletions
@@ -13,6 +13,7 @@ export function MapCanvas() {
citySummariesByName: store.citySummariesByName,
onClosePanel: store.closePanel,
onEnsureCityDetail: store.ensureCityDetail,
onMapInteractionChange: store.setMapInteractionActive,
onRegisterStopMotion: store.registerMapStopMotion,
onSelectCity: (cityName) => {
void store.selectCity(cityName);
+6 -2
View File
@@ -47,6 +47,7 @@ interface DashboardStoreValue extends DashboardState {
selectedMarketScan: MarketScan | null;
selectedDetail: CityDetail | null;
selectCity: (cityName: string) => Promise<void>;
setMapInteractionActive: (active: boolean) => void;
setForecastDate: (dateStr: string | null) => void;
marketScanByCityName: Record<string, MarketScan>;
}
@@ -254,6 +255,7 @@ export function DashboardStoreProvider({
string | null
>(null);
const [futureModalDate, setFutureModalDate] = useState<string | null>(null);
const [isMapInteracting, setIsMapInteracting] = useState(false);
const [loadingState, setLoadingState] = useState<LoadingState>(
getInitialLoadingState,
);
@@ -747,8 +749,9 @@ export function DashboardStoreProvider({
void (async () => {
await runQueue(priorityQueue, EAGER_SUMMARY_PRIORITY_CONCURRENCY);
if (!active) return;
if (isMapInteracting) return;
cancelIdleSchedule = scheduleWhenBrowserIdle(() => {
if (!active) return;
if (!active || isMapInteracting) return;
void runQueue(
backgroundQueue,
EAGER_SUMMARY_BACKGROUND_CONCURRENCY,
@@ -760,7 +763,7 @@ export function DashboardStoreProvider({
active = false;
cancelIdleSchedule();
};
}, [cities, loadingState.refresh]);
}, [cities, isMapInteracting, loadingState.refresh]);
const selectCity = async (cityName: string) => {
setSelectedCity(cityName);
@@ -1066,6 +1069,7 @@ export function DashboardStoreProvider({
selectedDetail,
selectedForecastDate,
selectCity,
setMapInteractionActive: setIsMapInteracting,
setForecastDate: (dateStr: string | null) =>
setSelectedForecastDate(dateStr),
marketScanByCityName,
+44
View File
@@ -19,6 +19,7 @@ interface UseLeafletMapArgs {
cityName: string,
force?: boolean,
) => Promise<CityDetail>;
onMapInteractionChange: (active: boolean) => void;
onRegisterStopMotion: (stopMotion: () => void) => void;
onSelectCity: (cityName: string) => void;
selectedCity: string | null;
@@ -195,6 +196,7 @@ export function useLeafletMap({
citySummariesByName,
onClosePanel,
onEnsureCityDetail,
onMapInteractionChange,
onRegisterStopMotion,
onSelectCity,
selectedCity,
@@ -218,6 +220,10 @@ export function useLeafletMap({
const onRegisterStopMotionRef = useRef(onRegisterStopMotion);
const onSelectCityRef = useRef(onSelectCity);
const onEnsureCityDetailRef = useRef(onEnsureCityDetail);
const onMapInteractionChangeRef = useRef(onMapInteractionChange);
const interactionIdleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(
null,
);
useEffect(() => {
onClosePanelRef.current = onClosePanel;
@@ -235,6 +241,10 @@ export function useLeafletMap({
onEnsureCityDetailRef.current = onEnsureCityDetail;
}, [onEnsureCityDetail]);
useEffect(() => {
onMapInteractionChangeRef.current = onMapInteractionChange;
}, [onMapInteractionChange]);
useEffect(() => {
suspendMotionRef.current = suspendMotion;
}, [suspendMotion]);
@@ -278,8 +288,42 @@ export function useLeafletMap({
};
map.on("click", handleMapClick);
const markInteracting = () => {
if (interactionIdleTimerRef.current) {
clearTimeout(interactionIdleTimerRef.current);
interactionIdleTimerRef.current = null;
}
onMapInteractionChangeRef.current(true);
};
const markIdleSoon = () => {
if (interactionIdleTimerRef.current) {
clearTimeout(interactionIdleTimerRef.current);
}
interactionIdleTimerRef.current = setTimeout(() => {
interactionIdleTimerRef.current = null;
onMapInteractionChangeRef.current(false);
}, 700);
};
map.on("movestart", markInteracting);
map.on("zoomstart", markInteracting);
map.on("dragstart", markInteracting);
map.on("moveend", markIdleSoon);
map.on("zoomend", markIdleSoon);
return () => {
onRegisterStopMotionRef.current(() => {});
if (interactionIdleTimerRef.current) {
clearTimeout(interactionIdleTimerRef.current);
interactionIdleTimerRef.current = null;
}
onMapInteractionChangeRef.current(false);
map.off("movestart", markInteracting);
map.off("zoomstart", markInteracting);
map.off("dragstart", markInteracting);
map.off("moveend", markIdleSoon);
map.off("zoomend", markIdleSoon);
map.off("click", handleMapClick);
map.remove();
mapRef.current = null;