Fix flyover button clickability and camera positioning

This commit is contained in:
(jenkins)
2026-03-16 23:35:22 +00:00
parent 8be3e04803
commit 259fdf1e10
2 changed files with 73 additions and 6 deletions
+70
View File
@@ -9,10 +9,12 @@ const APP = () => {
const mapRef = useRef(null);
const startMarkerRef = useRef(null);
const cityMarkersRef = useRef([]);
const animationRef = useRef(null);
const [selectedPoint, setSelectedPoint] = useState({ lat: 51.5074, lon: -0.1278 });
const [direction, setDirection] = useState(45);
const [lineOfSightData, setLineOfSightData] = useState(null);
const [loading, setLoading] = useState(false);
const [isPlaying, setIsPlaying] = useState(false);
const [mapStyle, setMapStyle] = useState('light'); // 'light' or 'dark'
const [tolerance, setTolerance] = useState(50);
const [selectedCity, setSelectedCity] = useState(null);
@@ -74,6 +76,7 @@ const APP = () => {
});
return () => {
if (animationRef.current) cancelAnimationFrame(animationRef.current);
if (mapRef.current) mapRef.current.remove();
};
}, []); // Run only once
@@ -108,6 +111,11 @@ const APP = () => {
}, [isLocked]);
const handleStartAgain = () => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
setIsPlaying(false);
}
setIsLocked(false);
setLineOfSightData(null);
setSelectedCity(null);
@@ -122,6 +130,14 @@ const APP = () => {
if (mapRef.current.getLayer('preview-line')) {
mapRef.current.setLayoutProperty('preview-line', 'visibility', 'visible');
}
// Reset map pitch and zoom
mapRef.current.flyTo({
center: [selectedPoint.lon, selectedPoint.lat],
zoom: 3,
pitch: 0,
bearing: 0
});
}
};
@@ -132,6 +148,60 @@ const APP = () => {
}
};
const startFlyOver = () => {
if (!lineOfSightData || !mapRef.current) return;
if (isPlaying) {
if (animationRef.current) cancelAnimationFrame(animationRef.current);
setIsPlaying(false);
return;
}
setIsPlaying(true);
const coordinates = lineOfSightData.line_coordinates.map(c => [c.lon, c.lat]);
const route = turf.lineString(coordinates);
const duration = 20000; // 20 seconds for the full flyover
const startTime = performance.now();
const routeDistance = turf.length(route);
function animate(currentTime) {
if (!mapRef.current) return;
const elapsed = currentTime - startTime;
const phase = Math.min(elapsed / duration, 1); // 0 to 1
// Stop when we reach the end
if (phase >= 1) {
setIsPlaying(false);
return;
}
const currentDist = routeDistance * phase;
// Look 100km ahead, camera is at the current distance
const target = turf.along(route, Math.min(currentDist + 100, routeDistance)).geometry.coordinates;
const eye = turf.along(route, currentDist).geometry.coordinates;
const camera = mapRef.current.getFreeCameraOptions();
// Position camera 50,000m (50km) above the 'eye' point
camera.position = maplibregl.MercatorCoordinate.fromLngLat(
{ lng: eye[0], lat: eye[1] },
50000
);
// Look at the target point
camera.lookAtPoint({ lng: target[0], lat: target[1] });
mapRef.current.setFreeCameraOptions(camera);
animationRef.current = requestAnimationFrame(animate);
}
animationRef.current = requestAnimationFrame(animate);
};
useEffect(() => {
// Update preview whenever point or direction changes
if (mapRef.current && mapRef.current.isStyleLoaded()) {
+3 -6
View File
@@ -126,16 +126,13 @@
opacity: 0.8;
}
.disabled-controls input, .disabled-controls .action-btn {
.disabled-controls input {
pointer-events: none;
cursor: not-allowed;
}
.action-btn-secondary {
pointer-events: auto !important;
}
.setting-row button {
/* Allow action buttons and settings buttons to work even when locked */
.action-btn, .action-btn-secondary, .setting-row button {
pointer-events: auto !important;
}