🗺️

MapLibre GL JSでVue3コンポーネントをポップアップに表示する

2024/06/25に公開

MapLibreで地図上にポップアップを表示する場合、setHTML内でDOMを文字列として与えるとポップアップ内容として表示することができます。

MapLibre 公式による例

このDOM内容をVueコンポーネントで置き換えるための方法です。

概要

  • Vue3のcreateAppでVueアプリケーションを作成
  • MapLibreのsetDOMContentでポップアップに追加

全体のコード

地図上をクリックするとその座標をポップアップ表示するコードです。

MapLibreMap.vue - MapLibreを表示するコンポーネント

MapLibreMap.vue
<script setup lang="ts">
import 'maplibre-gl/dist/maplibre-gl.css'
import { Map, Popup } from 'maplibre-gl'
import { onMounted, App, createApp } from 'vue'
import PopupComponent from './PopupComponent.vue';
onMounted(() => {
    const map = new Map({
        container: 'map',
        //地理院Vector(仮称)
        style: 'https://gsi-cyberjapan.github.io/gsivectortile-mapbox-gl-js/pale.json',
        //横浜駅
        center: [139.6225, 35.466111],
        zoom: 13,
    })

    //地図をクリックした時ポップアップ表示
    const clickPopup = new Popup({ closeOnClick: false });
    let popupApp: App;   
    map.on('click', (e) => {
        if (popupApp) {
            popupApp.unmount();
        }
        popupApp = createApp(PopupComponent, {
            lat: e.lngLat.lat, lng: e.lngLat.lng
        });
        const popupNode = document.createElement('div');
        popupApp.mount(popupNode);
        clickPopup.setDOMContent(popupNode);
        clickPopup.setLngLat(e.lngLat).addTo(map);
    });
});
</script>
<template>
    <div id="map"></div>
</template>
<style scoped>
#map {
    height: 100vh;
}
</style>

PopupComponent.vue - ポップアップに追加するコンポーネント

PopupComponent.vue
<template>
    <div>緯度:{{ lat }}</div>
    <div>経度:{{ lng }}</div>
</template>

<script setup lang="ts">
defineProps({
    lat: {
        type: Number,
        required: true,
    },
    lng: {
        type: Number,
        required: true,
    }
});
</script>

解説

宣言

const clickPopup = new Popup({ closeOnClick: false });
let popupApp: App;

イベントの外で宣言をします。

Vueアプリケーションを作成する

Vue3ではcreateAppでVueアプリケーションを作成します。

if (popupApp) {
    popupApp.unmount();
}
popupApp = createApp(PopupComponent, {
    lat: e.lngLat.lat, lng: e.lngLat.lng
});

すでにVueアプリケーションが存在している場合はunmountします。
追加するコンポーネントを指定してpropsに与える内容を指定します。

setDOMContentで追加する

const popupNode = document.createElement('div');
popupApp.mount(popupNode);
clickPopup.setDOMContent(popupNode);

divエレメントを作成しVueアプリケーションをmountします。
そしてsetHTMLの代わりにsetDOMContentでポップアップに追加します。

地図に追加

clickPopup.setLngLat(e.lngLat).addTo(map);

緯度経度を指定してMapLibreに追加し表示します。

Discussion