Spaces:
Sleeping
Fix three critical particle glitches
Browse files1. FIXED: 10m/100m wind toggle getting stuck when turned off
- Added robust layer cleanup with try/catch error handling
- Always set layer variables to null when disabling
- Improved toggle reliability
2. FIXED: Particles not clearing immediately on pan/zoom
- Added movestart/zoomstart event handlers for instant clearing
- Particles now disappear immediately when interaction begins
- Clean reload after movement ends
3. FIXED: Long particle artifacts at far zoom levels
- Reduced velocityScale (0.02β0.015 for 10m, 0.025β0.018 for 100m)
- Shortened particle life (particleAge: 60/70 frames)
- Reduced velocity tail lengths to prevent map-spanning artifacts
- Added frameRate control for better performance
π€ Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
@@ -520,19 +520,21 @@ def create_wind_map(region="global"):
|
|
520 |
angleConvention: "bearingCW",
|
521 |
showCardinal: true
|
522 |
}},
|
523 |
-
velocityScale: 0.
|
524 |
opacity: 0.9,
|
525 |
maxVelocity: 20,
|
526 |
-
particleMultiplier: 0.
|
527 |
-
lineWidth:
|
528 |
colorScale: getColorScale('10m'),
|
529 |
-
//
|
|
|
|
|
530 |
velocityAgeScale: [
|
531 |
-
[0,
|
532 |
-
[3,
|
533 |
-
[8,
|
534 |
-
[15,
|
535 |
-
[25,
|
536 |
]
|
537 |
}});
|
538 |
}}
|
@@ -550,19 +552,21 @@ def create_wind_map(region="global"):
|
|
550 |
angleConvention: "bearingCW",
|
551 |
showCardinal: true
|
552 |
}},
|
553 |
-
velocityScale: 0.
|
554 |
opacity: 0.8,
|
555 |
maxVelocity: 30,
|
556 |
-
particleMultiplier: 0.
|
557 |
-
lineWidth: 2.
|
558 |
colorScale: getColorScale('100m'),
|
559 |
-
//
|
|
|
|
|
560 |
velocityAgeScale: [
|
561 |
-
[0,
|
562 |
-
[5,
|
563 |
-
[12,
|
564 |
-
[20,
|
565 |
-
[35,
|
566 |
]
|
567 |
}});
|
568 |
}}
|
@@ -585,34 +589,46 @@ def create_wind_map(region="global"):
|
|
585 |
// Function to toggle 10m wind layer
|
586 |
function toggle10mLayer() {{
|
587 |
show10m = !show10m;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
588 |
if (show10m) {{
|
589 |
-
if (current10mLayer) map.removeLayer(current10mLayer);
|
590 |
current10mLayer = create10mLayer();
|
591 |
current10mLayer.addTo(map);
|
592 |
console.log("β
10m wind layer enabled");
|
593 |
}} else {{
|
594 |
-
|
595 |
-
map.removeLayer(current10mLayer);
|
596 |
-
current10mLayer = null;
|
597 |
-
console.log("β 10m wind layer disabled");
|
598 |
-
}}
|
599 |
}}
|
600 |
}}
|
601 |
|
602 |
// Function to toggle 100m wind layer
|
603 |
function toggle100mLayer() {{
|
604 |
show100m = !show100m;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
605 |
if (show100m) {{
|
606 |
-
if (current100mLayer) map.removeLayer(current100mLayer);
|
607 |
current100mLayer = create100mLayer();
|
608 |
current100mLayer.addTo(map);
|
609 |
console.log("β
100m wind layer enabled");
|
610 |
}} else {{
|
611 |
-
|
612 |
-
map.removeLayer(current100mLayer);
|
613 |
-
current100mLayer = null;
|
614 |
-
console.log("β 100m wind layer disabled");
|
615 |
-
}}
|
616 |
}}
|
617 |
}}
|
618 |
|
@@ -642,41 +658,57 @@ def create_wind_map(region="global"):
|
|
642 |
console.log("π« CLEARING all particles immediately...");
|
643 |
if (current10mLayer && map.hasLayer(current10mLayer)) {{
|
644 |
map.removeLayer(current10mLayer);
|
|
|
645 |
console.log("π« 10m particles cleared");
|
646 |
}}
|
647 |
if (current100mLayer && map.hasLayer(current100mLayer)) {{
|
648 |
map.removeLayer(current100mLayer);
|
|
|
649 |
console.log("π« 100m particles cleared");
|
650 |
}}
|
651 |
}}
|
652 |
|
653 |
-
// Function to reload particles after pan/zoom
|
654 |
function reloadParticlesAfterMove() {{
|
655 |
-
console.log("β‘
|
656 |
|
|
|
657 |
if (show10m) {{
|
658 |
-
console.log("β‘ Creating new 10m particles...");
|
659 |
current10mLayer = create10mLayer();
|
660 |
current10mLayer.addTo(map);
|
|
|
661 |
}}
|
662 |
|
663 |
if (show100m) {{
|
664 |
-
console.log("β‘ Creating new 100m particles...");
|
665 |
current100mLayer = create100mLayer();
|
666 |
current100mLayer.addTo(map);
|
|
|
667 |
}}
|
668 |
|
669 |
-
console.log("
|
670 |
}}
|
671 |
|
672 |
-
//
|
673 |
-
map.on('movestart',
|
674 |
-
|
675 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
676 |
|
677 |
-
map.on('moveend', reloadParticlesAfterMove); // Reload when pan ends
|
678 |
-
map.on('zoomend', reloadParticlesAfterMove); // Reload when zoom ends
|
679 |
-
map.on('dragend', reloadParticlesAfterMove); // Reload when drag ends
|
680 |
|
681 |
// Event handler for theme changes
|
682 |
map.on('baselayerchange', function() {{
|
|
|
520 |
angleConvention: "bearingCW",
|
521 |
showCardinal: true
|
522 |
}},
|
523 |
+
velocityScale: 0.015, // Reduced scale to prevent long artifacts
|
524 |
opacity: 0.9,
|
525 |
maxVelocity: 20,
|
526 |
+
particleMultiplier: 0.008, // Fewer particles for better performance
|
527 |
+
lineWidth: 1.5, // Thinner lines
|
528 |
colorScale: getColorScale('10m'),
|
529 |
+
frameRate: 20, // Controlled frame rate
|
530 |
+
particleAge: 60, // Shorter particle life to prevent artifacts
|
531 |
+
// Zoom-aware velocity scaling to prevent long particles at far zoom
|
532 |
velocityAgeScale: [
|
533 |
+
[0, 10], // Very slow winds = very short tails
|
534 |
+
[3, 20], // Low winds = short tails
|
535 |
+
[8, 40], // Moderate winds = medium tails
|
536 |
+
[15, 60], // Fast winds = longer tails
|
537 |
+
[25, 80] // Very fast winds = longest tails (reduced)
|
538 |
]
|
539 |
}});
|
540 |
}}
|
|
|
552 |
angleConvention: "bearingCW",
|
553 |
showCardinal: true
|
554 |
}},
|
555 |
+
velocityScale: 0.018, // Reduced scale to prevent long artifacts
|
556 |
opacity: 0.8,
|
557 |
maxVelocity: 30,
|
558 |
+
particleMultiplier: 0.006, // Fewer particles for better performance
|
559 |
+
lineWidth: 2.0, // Slightly thinner lines
|
560 |
colorScale: getColorScale('100m'),
|
561 |
+
frameRate: 20, // Controlled frame rate
|
562 |
+
particleAge: 70, // Shorter particle life to prevent artifacts
|
563 |
+
// Zoom-aware velocity scaling to prevent long particles at far zoom
|
564 |
velocityAgeScale: [
|
565 |
+
[0, 15], // Very slow winds = short tails
|
566 |
+
[5, 30], // Low winds = medium tails
|
567 |
+
[12, 50], // Moderate winds = longer tails
|
568 |
+
[20, 70], // Fast winds = long tails (reduced)
|
569 |
+
[35, 90] // Very fast winds = longest tails (reduced)
|
570 |
]
|
571 |
}});
|
572 |
}}
|
|
|
589 |
// Function to toggle 10m wind layer
|
590 |
function toggle10mLayer() {{
|
591 |
show10m = !show10m;
|
592 |
+
|
593 |
+
// Always clean up existing layer first
|
594 |
+
if (current10mLayer) {{
|
595 |
+
try {{
|
596 |
+
map.removeLayer(current10mLayer);
|
597 |
+
}} catch(e) {{
|
598 |
+
console.warn("Error removing 10m layer:", e);
|
599 |
+
}}
|
600 |
+
current10mLayer = null;
|
601 |
+
}}
|
602 |
+
|
603 |
if (show10m) {{
|
|
|
604 |
current10mLayer = create10mLayer();
|
605 |
current10mLayer.addTo(map);
|
606 |
console.log("β
10m wind layer enabled");
|
607 |
}} else {{
|
608 |
+
console.log("β 10m wind layer disabled");
|
|
|
|
|
|
|
|
|
609 |
}}
|
610 |
}}
|
611 |
|
612 |
// Function to toggle 100m wind layer
|
613 |
function toggle100mLayer() {{
|
614 |
show100m = !show100m;
|
615 |
+
|
616 |
+
// Always clean up existing layer first
|
617 |
+
if (current100mLayer) {{
|
618 |
+
try {{
|
619 |
+
map.removeLayer(current100mLayer);
|
620 |
+
}} catch(e) {{
|
621 |
+
console.warn("Error removing 100m layer:", e);
|
622 |
+
}}
|
623 |
+
current100mLayer = null;
|
624 |
+
}}
|
625 |
+
|
626 |
if (show100m) {{
|
|
|
627 |
current100mLayer = create100mLayer();
|
628 |
current100mLayer.addTo(map);
|
629 |
console.log("β
100m wind layer enabled");
|
630 |
}} else {{
|
631 |
+
console.log("β 100m wind layer disabled");
|
|
|
|
|
|
|
|
|
632 |
}}
|
633 |
}}
|
634 |
|
|
|
658 |
console.log("π« CLEARING all particles immediately...");
|
659 |
if (current10mLayer && map.hasLayer(current10mLayer)) {{
|
660 |
map.removeLayer(current10mLayer);
|
661 |
+
current10mLayer = null;
|
662 |
console.log("π« 10m particles cleared");
|
663 |
}}
|
664 |
if (current100mLayer && map.hasLayer(current100mLayer)) {{
|
665 |
map.removeLayer(current100mLayer);
|
666 |
+
current100mLayer = null;
|
667 |
console.log("π« 100m particles cleared");
|
668 |
}}
|
669 |
}}
|
670 |
|
671 |
+
// Function to reload particles after pan/zoom
|
672 |
function reloadParticlesAfterMove() {{
|
673 |
+
console.log("β‘ PAN/ZOOM END: Reloading particles...");
|
674 |
|
675 |
+
// Recreate and add back active layers
|
676 |
if (show10m) {{
|
|
|
677 |
current10mLayer = create10mLayer();
|
678 |
current10mLayer.addTo(map);
|
679 |
+
console.log("β‘ 10m particles reloaded");
|
680 |
}}
|
681 |
|
682 |
if (show100m) {{
|
|
|
683 |
current100mLayer = create100mLayer();
|
684 |
current100mLayer.addTo(map);
|
685 |
+
console.log("β‘ 100m particles reloaded");
|
686 |
}}
|
687 |
|
688 |
+
console.log("β
Particle reload complete!");
|
689 |
}}
|
690 |
|
691 |
+
// Add pan/zoom event handlers for immediate particle clearing
|
692 |
+
map.on('movestart', function() {{
|
693 |
+
console.log("π« PAN START: Clearing particles...");
|
694 |
+
clearAllParticles();
|
695 |
+
}});
|
696 |
+
|
697 |
+
map.on('zoomstart', function() {{
|
698 |
+
console.log("π« ZOOM START: Clearing particles...");
|
699 |
+
clearAllParticles();
|
700 |
+
}});
|
701 |
+
|
702 |
+
map.on('moveend', function() {{
|
703 |
+
console.log("β‘ PAN END: Reloading particles...");
|
704 |
+
setTimeout(reloadParticlesAfterMove, 100);
|
705 |
+
}});
|
706 |
+
|
707 |
+
map.on('zoomend', function() {{
|
708 |
+
console.log("β‘ ZOOM END: Reloading particles...");
|
709 |
+
setTimeout(reloadParticlesAfterMove, 100);
|
710 |
+
}});
|
711 |
|
|
|
|
|
|
|
712 |
|
713 |
// Event handler for theme changes
|
714 |
map.on('baselayerchange', function() {{
|