nuxt-mapbox
Version:
Elegant Mapbox GL JS integration with Nuxt
88 lines (87 loc) • 3.69 kB
JavaScript
import { whenever } from "@vueuse/core";
import { inject, isRef, onUnmounted, ref, useMapbox, useMapboxMarker, useMapboxMarkerRef, useState, watch } from "#imports";
import mapboxgl from "mapbox-gl";
export function defineMapboxMarker(markerID, options, markerHTML, callback, mapID = "") {
if (import.meta.server) return;
if (useMapboxMarkerRef(markerID).value) {
console.warn(`Mapbox marker with ID '${markerID}' was initialized multiple times. This can cause unexpected behaviour.`);
return useMapboxMarkerRef(markerID);
}
const markerRef = ref();
const mapId = inject("MapID");
function initMarker() {
const markerOptions = isRef(options) ? options.value : options;
if (markerHTML) {
whenever(markerHTML, () => {
if (markerHTML.value) {
markerHTML.value.hidden = false;
const mapbox_marker_instances = useState("mapbox_marker_instances", () => {
return {};
});
mapbox_marker_instances.value[markerID] = new mapboxgl.Marker({ element: markerHTML.value, ...markerOptions });
markerRef.value = mapbox_marker_instances.value[markerID];
if (callback) callback(markerRef.value);
useMapbox(mapId || mapID, (map) => {
if (markerRef.value)
markerRef?.value?.setLngLat(markerOptions.lnglat).addTo(map);
});
}
}, { immediate: true });
return markerRef;
} else {
const mapbox_marker_instances = useState("mapbox_marker_instances", () => {
return {};
});
mapbox_marker_instances.value[markerID] = new mapboxgl.Marker(markerOptions);
const marker = mapbox_marker_instances.value[markerID];
useMapbox(mapId || mapID, (map) => {
marker.setLngLat(markerOptions.lnglat).addTo(map);
});
return marker;
}
}
if (isRef(options)) {
watch(options, (newOptions, oldOptions) => {
const currentMarker = useMapboxMarkerRef(markerID);
if (newOptions.draggable !== oldOptions?.draggable && newOptions.draggable !== void 0) {
currentMarker.value?.setDraggable(newOptions.draggable);
}
if (newOptions.offset !== oldOptions?.offset && newOptions.offset !== void 0) {
currentMarker.value?.setOffset(newOptions.offset);
}
if (newOptions.pitchAlignment !== oldOptions?.pitchAlignment && newOptions.pitchAlignment !== void 0) {
currentMarker.value?.setPitchAlignment(newOptions.pitchAlignment);
}
if (newOptions.rotationAlignment !== oldOptions?.rotationAlignment && newOptions.rotationAlignment !== void 0) {
currentMarker.value?.setRotationAlignment(newOptions.rotationAlignment);
}
if (newOptions.rotation !== oldOptions?.rotation && newOptions.rotation !== void 0) {
currentMarker.value?.setRotation(newOptions.rotation);
}
if (currentMarker.value?.getLngLat() !== options.value.lnglat) {
currentMarker.value?.setLngLat(options.value.lnglat);
}
}, { deep: true });
useMapboxMarker(markerID, (marker) => {
marker.on("drag", () => {
const newLngLat = marker.getLngLat();
if (Array.isArray(options.value.lnglat)) {
options.value.lnglat = newLngLat.toArray();
} else {
options.value.lnglat = newLngLat;
}
});
});
}
onUnmounted(() => {
const currentMarker = useMapboxMarkerRef(markerID);
if (currentMarker.value) {
currentMarker.value.remove();
const mapbox_marker_instances = useState("mapbox_marker_instances", () => {
return {};
});
delete mapbox_marker_instances.value[markerID];
}
});
return initMarker();
}