はじめに
この記事は 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
動作確認
位置を追従しながら、GPSログを保存しているのを確認できました
最後に
本記事では現在位置の表示・追従とログの保存について解説しました
次はログを地図上に描画していきます
本記事は以上になりますありがとうございました