Day21 要來做個羅盤
const [geolocation, setGeolocation] = useState<Geolocation>({
speed: 0,
heading: 0,
});
const [error, setError] = useState<string | null>(null);
const [watchId, setWatchId] = useState<number | null>(null);
const startWatching = (): void => {
if ("geolocation" in navigator) {
const id: number = navigator.geolocation.watchPosition(
(position: GeolocationPosition) => {
setGeolocation({
speed: position.coords.speed || 0,
heading: position.coords.heading || 0,
});
},
(err: GeolocationPositionError) => {
setError(err.message);
},
{
enableHighAccuracy: true,
maximumAge: 0,
timeout: 5000,
}
);
setWatchId(id);
} else {
setError("Geolocation is not supported by this browser.");
}
};
const stopWatching = (): void => {
if (watchId !== null) {
navigator.geolocation.clearWatch(watchId);
setWatchId(null);
}
};
const handleStartStop = (): void => {
if (watchId === null) {
startWatching();
} else {
stopWatching();
}
};
const compassStyle: React.CSSProperties = {
transform: `rotate(${geolocation.heading}deg)`,
};
return (
<div className="flex flex-col items-center justify-center h-screen bg-gray-100">
{error && <div className="text-red-500 mb-4">{error}</div>}
<div className="text-4xl font-bold mb-4">
Speed: {geolocation.speed.toFixed(2)} m/s
</div>
<div className="relative w-40 h-40 mb-4">
<div
className="absolute inset-0 border-4 border-blue-500 rounded-full"
style={compassStyle}
>
<div className="absolute top-0 left-1/2 -ml-1 w-2 h-8 bg-red-500"></div>
</div>
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-2xl font-bold">
{Math.round(geolocation.heading)}°
</div>
</div>
<button
type="button"
onClick={handleStartStop}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
{watchId !== null ? "Stop Watching" : "Start Watching"}
</button>
</div>
);
}