Untitled
unknown
plain_text
2 years ago
11 kB
12
Indexable
import React, { useState, useEffect } from 'react';
function GeolocationTracker() {
const [isCollecting, setIsCollecting] = useState(true);
const [startTime, setStartTime] = useState(null);
const [lastTime, setLastTime] = useState(null);
const [distance, setDistance] = useState(0);
const [startPosition, setStartPosition] = useState(null);
const [lastPosition, setLastPosition] = useState(null);
const [speed, setSpeed] = useState(0);
const [accelerationY, setAccelerationY] = useState(0);
const [accuracy, setAccuracy] = useState(null);
const [isDriving, setIsDriving] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const [speedProfile, setSpeedProfile] = useState([]);
useEffect(() => {
if (!isCollecting) return;
const watchId = navigator.geolocation.watchPosition(
function(position) {
const currentTime = new Date().getTime();
if (!startTime) {
setStartTime(currentTime);
setLastTime(currentTime);
setStartPosition({ latitude: position.coords.latitude, longitude: position.coords.longitude });
setLastPosition({ latitude: position.coords.latitude, longitude: position.coords.longitude });
} else {
const deltaTime = (currentTime - lastTime) / 1000; // in seconds
const currentDistance = calculateDistance(lastPosition.latitude, lastPosition.longitude, position.coords.latitude, position.coords.longitude);
setDistance(distance + currentDistance);
const currentSpeed = currentDistance / deltaTime;
setSpeed(currentSpeed);
setLastTime(currentTime);
setLastPosition({ latitude: position.coords.latitude, longitude: position.coords.longitude });
// Add data to speed profile
setSpeedProfile(prevProfile => [...prevProfile, { time: currentTime, speed: currentSpeed, distance: distance }]);
}
setAccuracy(position.coords.accuracy);
setIsDriving(position.coords.speed > 0.1); // Assuming speed > 0.1 m/s indicates driving
},
function(error) {
console.error('Error getting geolocation:', error);
},
{
maximumAge: 0,
enableHighAccuracy: true
}
);
const handleMotionEvent = (event) => {
setAccelerationY(event.accelerationIncludingGravity.y);
};
window.addEventListener('devicemotion', handleMotionEvent);
const intervalId = setInterval(() => {
setCurrentTime((new Date().getTime() - startTime) / 1000);
}, 1000);
return () => {
clearInterval(intervalId);
navigator.geolocation.clearWatch(watchId);
window.removeEventListener('devicemotion', handleMotionEvent);
};
}, [isCollecting, startTime, lastTime, distance, lastPosition]);
const calculateDistance = (lat1, lon1, lat2, lon2) => {
const R = 6371e3; // metres
const φ1 = (lat1 * Math.PI) / 180; // φ, λ in radians
const φ2 = (lat2 * Math.PI) / 180;
const Δφ = ((lat2 - lat1) * Math.PI) / 180;
const Δλ = ((lon2 - lon1) * Math.PI) / 180;
const a =
Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c; // in meters
};
const clearData = () => {
setIsCollecting(false);
setStartTime(null);
setLastTime(null);
setDistance(0);
setStartPosition(null);
setLastPosition(null);
setSpeed(0);
setAccelerationY(0);
setAccuracy(null);
setIsDriving(false);
setCurrentTime(0);
setSpeedProfile([]);
};
const restartCollecting = () => {
setIsCollecting(true);
setStartTime(null);
setLastTime(null);
setDistance(0);
setStartPosition(null);
setLastPosition(null);
setSpeed(0);
setAccelerationY(0);
setAccuracy(null);
setIsDriving(false);
setCurrentTime(0);
setSpeedProfile([]);
};
return (
<div style={styles.overlay}>
<div className="container" style={styles.container}>
<h2 style={{color:'white'}}>Speed Coach</h2>
<table style={styles.table}>
<tbody>
<tr style={styles.row}>
<td style={styles.label}>State:</td>
<td style={styles.data}>{isDriving ? 'Driving' : 'Standing'}</td>
</tr>
<tr style={styles.row}>
<td style={styles.label}>GPS Speed:</td>
<td style={styles.data}>{speed.toFixed(2)} m/s</td>
</tr>
<tr style={styles.row}>
<td style={styles.label}>Y Acceleration:</td>
<td style={styles.data}>{accelerationY.toFixed(2)}</td>
</tr>
{/*<tr style={styles.row}>*/}
{/* <td style={styles.label}>GPS Position:</td>*/}
{/* <td style={styles.data}>*/}
{/* {`lat: ${lastPosition?.latitude?.toFixed(6) || 'N/A'}, lng: ${lastPosition?.longitude?.toFixed(6) || 'N/A'}`}*/}
{/* </td>*/}
{/*</tr>*/}
<tr style={styles.row}>
<td style={styles.label}>GPS Accuracy:</td>
<td style={styles.data}>{accuracy ? `${accuracy} meters` : 'N/A'}</td>
</tr>
<tr style={styles.row}>
<td style={styles.label}>Distance from start:</td>
<td style={styles.data}>{distance.toFixed(2)} meters</td>
</tr>
</tbody>
</table>
{/*<div style={styles.listViewContainer}>*/}
{/* <div style={styles.listView}>*/}
{/* <div style={styles.listViewItem}>*/}
{/* <p>Speed Profile Seconds</p>*/}
{/* {speedProfile.map((entry, index) => (*/}
{/* <p key={index}>{entry.time.toFixed(2)}</p>*/}
{/* ))}*/}
{/* </div>*/}
{/* <div style={styles.listViewItem}>*/}
{/* <p>km/h</p>*/}
{/* {speedProfile.map((entry, index) => (*/}
{/* <p key={index}>{((entry.speed * 3600) /*/}
{/* 1000).toFixed(2)}</p>*/}
{/* ))}*/}
{/* </div>*/}
{/* <div style={styles.listViewItem}>*/}
{/* <p>m</p>*/}
{/* {speedProfile.map((entry, index) => (*/}
{/* <p key={index}>{entry.distance.toFixed(2)}</p>*/}
{/* ))}*/}
{/* </div>*/}
{/* </div>*/}
{/*</div>*/}
<div style={styles.listViewContainer}>
<div style={styles.listViewHeader}>
<p>Speed Profile Seconds</p>
<p>km/h</p>
<p>m</p>
</div>
<div style={styles.listView}>
<div style={styles.listViewItem}>
{speedProfile.map((entry, index) => (
<p key={index}>{entry.time.toFixed(2)}</p>
))}
</div>
<div style={styles.listViewItem}>
{speedProfile.map((entry, index) => (
<p key={index}>{((entry.speed * 3600) /
1000).toFixed(2)}</p>
))}
</div>
<div style={styles.listViewItem}>
{speedProfile.map((entry, index) => (
<p key={index}>{entry.distance.toFixed(2)}</p>
))}
</div>
</div>
</div>
</div>
<button
style={styles.button}
onClick={isCollecting ? clearData : restartCollecting}
>
{isCollecting ? 'Clear' : 'Restart'}
</button>
</div>
);
}
const styles = {
overlay: {
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'black',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'column',
color: 'white',
},
container: {
backgroundColor: 'rgba(38,38,38,255)',
padding: '20px',
borderRadius: '8px',
width: '90%',
maxWidth: '400px',
textAlign: 'center',
marginBottom: '20px',
},
table: {
width: '100%',
borderCollapse: 'collapse',
marginBottom: '20px',
color: 'white',
},
row: {
borderBottom: '1px solid rgba(0, 0, 0, 0.1)',
},
label: {
textAlign: 'left',
padding: '10px',
fontWeight: 'bold',
},
data: {
textAlign: 'right',
padding: '10px',
},
button: {
marginTop: '20px',
padding: '10px 20px',
backgroundColor: 'purple',
color: '#fff',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
fontWeight: 'bold',
},
listViewContainer: {
width: '90%',
maxWidth: '400px',
backgroundColor: 'rgba(38,38,38,255)',
padding: '20px',
borderRadius: '8px',
textAlign: 'center',
color: 'white',
height: '150px',
overflowY: 'auto', // Add this line
position: 'relative', // Add this line
},
listViewHeader: {
display: 'flex',
top: '0', // Add this line
backgroundColor: 'rgba(38,38,38,255)', // Add this line
padding: '10px 0', // Add this line
justifyContent: 'space-between',
overflow:'false'
},
listView: {
display: 'flex',
justifyContent: 'space-between',
},
listViewItem: {
flex: 1,
justifyContent: 'space-between',
},
};
export default GeolocationTracker;
Editor is loading...
Leave a Comment