LoginSignup
11
1

ElixirDesktop MapLibreで現在位置の表示と追従

Last updated at Posted at 2023-12-23

はじめに

この記事は Elixirアドベントカレンダーのシリーズ4の22日目の記事です

今回はGPSログから地図で現在位置の表示とログの保存について解説します

現在位置の表示

mount時の処理に以下を追加します

  • 現在位置を取得
  • 地図のセンターを現在位置に設定
  • 現在位置にマーカーを追加
  • 地図にコントロールUIを追加

ロギング開始時の処理に以下を追加します

  • 地図のセンターを更新
  • マーカーの位置を更新
assets/js/hooks.js
Hooks.MapLibre = {
  mounted() {
-   const map = new maplibregl.Map({
-   container: "map",
-     style: "https://tile2.openstreetmap.jp/styles/osm-bright/style.json",
-     center: { lat: 33.30639, lng: 130.41806 },
-     zoom: 8,
-   });
-   window.map = map;

+   navigator.geolocation.getCurrentPosition((pos) => {
+     const init = [pos.coords.longitude, pos.coords.latitude]
+     const map = new maplibregl.Map({
+       container: "map",
+       style: "https://tile2.openstreetmap.jp/styles/osm-bright/style.json",
+       center: init,
+       zoom: 12,
+     });
+
+     map.on("load", () => {
+       map.addControl(new maplibregl.NavigationControl());
+     });
+
+     const user = new maplibregl.Marker().setLngLat(init).addTo(map);
+     window.user = user;
+     window.map = map;
+   });

    this.handleEvent("start_logging", () => {
      const watchID = navigator.geolocation.watchPosition((position) => {
        const coords = position.coords;
+       window.user.setLngLat([coords.longitude, coords.latitude]);
+       window.map.setCenter([coords.longitude, coords.latitude]);
        this.pushEvent("update", {
-         heading: coords.heading,
          lat: coords.latitude,
          lng: coords.longitude,
-         speed: coords.speed,
-         timestamp: position.timestamp,
        });
      });
      window.watchID = watchID;
    });

    this.handleEvent("stop_logging", () => {
      navigator.geolocation.clearWatch(window.watchID);
    });
  },
};

export default Hooks;

ライブラリの追加

移動距離が最後のログから100m離れていたら記録したいので、
100m移動したかの計算をGeoclacというライブラリを使ってlat,lngから2点間の距離を計算します

mix.exs
  defp deps do
    [
      ...
-     {:req, "~> 0.3"}
+     {:req, "~> 0.3"},
+     {:geocalc, "~> 0.8"}
    ]
  end

追加したら以下のコマンドを実行します

mix deps.get

ログの保存

最後のログから100m移動していたら保存するようにします

lib/spotter_web/live/route_live/show.ex
defmodule SpotterWeb.RouteLive.Show do
  use SpotterWeb, :live_view
  ...
  @impl true
  def handle_params(%{"id" => id}, _, socket) do
    {:noreply,
     socket
     |> assign(:page_title, page_title(socket.assigns.live_action))
     |> assign(:route, Loggers.get_route!(id))
+    |> assign(:pos, [0, 0])
     |> assign(:record, false)}
  end

- def handle_event("update", params, socket) do
+ def handle_event("update", %{"lat" => lat, "lng" => lng}, socket) do
-   IO.inspect(params) 
+   if Geocalc.distance_between(socket.assigns.pos, [lat, lng]) > 100 do
+     Loggers.create_position(%{lat: lat, lng: lng, route_id: socket.assigns.route.id})
+     {:noreply, assign(socket, :pos, [lat, lng])}
+   else
+     {:noreply, socket}
+   end
  end
end

動作確認

d0f1af2e6ee1855f0a2b9c390c1552b4.gif

位置を追従しながら、GPSログを保存しているのを確認できました

最後に

本記事では現在位置の表示・追従とログの保存について解説しました
次はログを地図上に描画していきます

本記事は以上になりますありがとうございました

11
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
1