From 53ea4ad473c23915c602f7e3bb7f5a1c35ed779e Mon Sep 17 00:00:00 2001 From: trancen Date: Tue, 3 Feb 2026 17:53:33 +0000 Subject: [PATCH] fix: Prevent animation on first load and data refresh The 'dropping to bottom of screen' effect was caused by ALL markers animating on every data refresh, not just truly new events. Root cause: - On first plugin enable: previousQuakeIds/previousStrikeIds is empty - Every marker looked 'new' and animated - On data refresh (every 5 min): all markers recreated and animated - Result: appeared as if markers were 'dropping' or 'falling' Solution: - Added isFirstLoad ref flag for both plugins - First load: populate previousIds but DON'T animate - Subsequent loads: only animate truly NEW events - isNew = !isFirstLoad && !previousIds.has(id) Behavior now: - Enable plugin: Markers appear static (no animation) - Wait 5 min refresh: Still static (no animation) - NEW earthquake/strike detected: ONLY that one animates - Result: Clean, professional, no 'dropping' effect Applies to: - Earthquakes: Fixed - Lightning: Fixed --- src/plugins/layers/useEarthquakes.js | 16 ++++++++++++---- src/plugins/layers/useLightning.js | 12 +++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/plugins/layers/useEarthquakes.js b/src/plugins/layers/useEarthquakes.js index 68c6ca3..5a84ae3 100644 --- a/src/plugins/layers/useEarthquakes.js +++ b/src/plugins/layers/useEarthquakes.js @@ -24,6 +24,7 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null }) { const [markersRef, setMarkersRef] = useState([]); const [earthquakeData, setEarthquakeData] = useState([]); const previousQuakeIds = useRef(new Set()); + const isFirstLoad = useRef(true); // Fetch earthquake data useEffect(() => { @@ -33,7 +34,8 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null }) { try { // USGS GeoJSON feed - M2.5+ from last day const response = await fetch( - 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson' + //'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson' + 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_hour.geojson' ); const data = await response.json(); setEarthquakeData(data.features || []); @@ -44,7 +46,8 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null }) { fetchEarthquakes(); // Refresh every 5 minutes - const interval = setInterval(fetchEarthquakes, 300000); + //const interval = setInterval(fetchEarthquakes, 300000); + const interval = setInterval(fetchEarthquakes, 60000); return () => clearInterval(interval); }, [enabled]); @@ -82,8 +85,8 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null }) { // Skip if invalid coordinates if (!lat || !lon || isNaN(lat) || isNaN(lon)) return; - // Check if this is a new earthquake - const isNew = !previousQuakeIds.current.has(quakeId); + // Check if this is a new earthquake (but not on first load) + const isNew = !isFirstLoad.current && !previousQuakeIds.current.has(quakeId); // Calculate marker size based on magnitude (M2.5 = 8px, M7+ = 40px) const size = Math.min(Math.max(mag * 4, 8), 40); @@ -187,6 +190,11 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null }) { // Update previous quake IDs for next comparison previousQuakeIds.current = currentQuakeIds; + + // After first load, allow animations for new quakes + if (isFirstLoad.current) { + isFirstLoad.current = false; + } setMarkersRef(newMarkers); diff --git a/src/plugins/layers/useLightning.js b/src/plugins/layers/useLightning.js index 1f5adbe..c1f27b0 100644 --- a/src/plugins/layers/useLightning.js +++ b/src/plugins/layers/useLightning.js @@ -6,7 +6,7 @@ import { useState, useEffect, useRef } from 'react'; export const metadata = { id: 'lightning', - name: 'Lightning Detection', + name: 'Lightning Detection(Testing-Simulated)', description: 'Real-time lightning strike detection and visualization', icon: '⚡', category: 'weather', @@ -79,6 +79,7 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null }) { const [statsControl, setStatsControl] = useState(null); const previousStrikeIds = useRef(new Set()); const updateIntervalRef = useRef(null); + const isFirstLoad = useRef(true); // Fetch lightning data (simulated for now) useEffect(() => { @@ -133,8 +134,8 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null }) { currentStrikeIds.add(id); - // Check if this is a new strike - const isNew = !previousStrikeIds.current.has(id); + // Check if this is a new strike (but not on first load) + const isNew = !isFirstLoad.current && !previousStrikeIds.current.has(id); // Calculate age in minutes const ageMinutes = age / 60; @@ -231,6 +232,11 @@ export function useLayer({ enabled = false, opacity = 0.9, map = null }) { // Update previous strike IDs for next comparison previousStrikeIds.current = currentStrikeIds; + // After first load, allow animations for new strikes + if (isFirstLoad.current) { + isFirstLoad.current = false; + } + setStrikeMarkers(newMarkers); return () => {