iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0

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>
  );
}

DEMO

https://codesandbox.io/p/devbox/day21-geolocation-nyvp3h


上一篇
[Day20]_Speech-Detection
下一篇
[Day22]_Follow-Along-Link-Highlighter
系列文
React30——用 React 探索 JavaScript30 的魅力30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言