@indoorequal/vue-maplibre-gl
Version:
Vue 3 plugin for maplibre-gl
105 lines (98 loc) • 2.39 kB
text/typescript
import {
createCommentVNode,
getCurrentInstance,
inject,
warn,
watch,
} from "vue";
import {
componentIdSymbol,
isLoadedSymbol,
mapSymbol,
sourceIdSymbol,
} from "@/lib/types";
import { useDisposableLayer } from "@/lib/composable/useDisposableLayer";
import {
genLayerOpts,
registerLayerEvents,
type LayersWithSource,
type LayerProps,
} from "@/lib/lib/layer.lib";
import { SourceLib } from "@/lib/lib/source.lib";
export function useLayer<T extends LayersWithSource>(
name: string,
props: LayerProps,
) {
const sourceId = inject(sourceIdSymbol);
if (!sourceId && !props.source) {
warn(
`${name} Layer: layer must be used inside source tag or source prop must be set`,
);
return;
}
const ci = getCurrentInstance()!,
map = inject(mapSymbol)!,
isLoaded = inject(isLoadedSymbol)!,
cid = inject(componentIdSymbol)!,
sourceRef = SourceLib.getSourceRef(cid, props.source || sourceId);
useDisposableLayer(props.layerId!, ci);
watch(
() => props.minzoom,
() =>
map.value!.setLayerZoomRange(
props.layerId!,
props.minzoom || 0,
props.maxzoom || 24,
),
);
watch(
() => props.maxzoom,
() =>
map.value!.setLayerZoomRange(
props.layerId!,
props.minzoom || 0,
props.maxzoom || 24,
),
);
watch(
() => props.layout,
(layout) => {
if (layout) {
for (const [property, value] of Object.entries(layout)) {
map.value!.setLayoutProperty(props.layerId!, property, value);
}
}
},
{ deep: true },
);
watch(
() => props.paint,
(paint) => {
if (paint) {
for (const [property, value] of Object.entries(paint)) {
map.value!.setPaintProperty(props.layerId!, property, value);
}
}
},
{ deep: true },
);
watch(
() => props.filter,
(f) => map.value!.setFilter(props.layerId!, f),
{ deep: true },
);
watch(
[isLoaded, sourceRef],
([il, src]) => {
if (il && (src || src === undefined)) {
map.value!.addLayer(
genLayerOpts<T>(props.layerId!, name, props, sourceId),
props.before || undefined,
);
registerLayerEvents(map.value!, props.layerId!, ci.vnode);
}
},
{ immediate: true },
);
return () => createCommentVNode(`${name} Layer`);
}