Extend vue3-openlayers
If you like to add a specific component wrapper based on an external library deviating from ol
or ol-ext
, please follow this guide.
Layer Plugins
If you like to add a specific map layer, you can create your own component and integrate it. Therefore the source component should be placed within a layer component. The composable useLayer
will help you implementing it. It will add the layer to the parent layer group, to a parent overview-map component or to the map itself based on usage and your component tree.
The example below demonstrates how a source called FooLayer
could be implemented:
<template>
<div>
<slot></slot>
</div>
</template>
<script setup lang="ts">
import { provide, shallowRef } from "vue";
import FooLayer from "ol/layer/FooLayer";
import usePropsAsObjectProperties from "@/composables/usePropsAsObjectProperties";
import useLayer from "@/composables/useLayer";
import {
layersCommonDefaultProps,
type LayersCommonProps,
} from "@/components/layers/LayersCommonProps";
const props = withDefaults(
defineProps<script
LayersCommonProps & {
myProp?: string;
}
>(),
{
...layersCommonDefaultProps,
myProp: "myProp",
},
);
// Create the layer
// Changes will be applied and the layer will be removed on unmount.
// The last parameter will receive the event names which should be handled by the target component.
// Common Layer events (https://openlayers.org/en/latest/apidoc/module-ol_layer_Layer-Layer.html) are already handled within the composable
// Check out the sources of the composable for more details.
const { layer } = useLayer(FooLayer, props, ['foo']);
// source components will rely on the layer (depends on the source type)
provide("vectorLayer", layer);
// provide("heatmapLayer", layer);
// provide("imageLayer", layer);
// provide("tileLayer", layer);
// provide("vectorImageLayer", layer);
// provide("vectorTileLayer", layer);
// provide("webglVectorLayer", layer);
defineExpose({
// see above ("provide")
vectorLayer: layer
// vectorLayer
// heatmapLayer
// imageLayer
// tileLayer
// vectorImageLayer
// vectorTileLayer
// webglVectorLayer
});
</script>
Source Plugins
If you like to add a specific map source (e. g. for vector or tile data), you can create your own component and integrate it with vue3-openlayers. Therefore the source component should be placed within a layer component. This allows you to inject either tileLayer
, imageLayer
, vectorLayer
or heatmapLayer
from the parent component. It gives you the ability to apply your source on this layer.
The example below demonstrates how a source called FooSource
could be implemented:
<template>
<div v-if="false"></div>
</template>
<script setup lang="ts">
import type { Ref } from "vue";
import { inject } from "vue";
import { useSource } from "vue3-openlayers";
// import the source to be wrapped in a component.
import FooSource, { type Options } from "foo-source";
// import the layer type, the source is applied to.
// It is defined by the parent component and injected below.
import type TileLayer from "ol/layer/Tile";
// import type ImageLayer from "ol/layer/Image";
// import type VectorLayer from "ol/layer/Vector";
// Define the options, the wrapper component can receive.
// In best case, they will be passed 1:1 from the original source.
const props = withDefaults(defineProps<Options>(), {
// you can define some default values here
});
// Inject the reference to the layer, the source will be applied to.
// The provide comes from a parent component
const layer = inject<Ref<TileLayer<FooSource>> | null>("tileLayer");
// const layer = inject<ImageLayer<FooSource> | null>("imageLayer");
// const layer = inject<Ref<VectorLayer<FooSource>> | null>("vectorLayer");
// const layer = inject<Ref<HeatmapLayer> | null>("heatmapLayer");
// Create the source and watch for changes of the source, the props or the parent layer.
// Changes will be applied and the source will be removed on unmount.
// The last parameter will receive the event names which should be handled by the target component.
// Check out the sources of the composable for more details.
const { source } = useSource(FooSource, layer, props, ["removefeature"]);
// Expose the layer and source, so it can be used as a `ref=""` on the element
defineExpose({
layer,
source,
});
</script>
For a live example, please checkout this demo.
Animation Plugins
The composable useAnimation
can and should be used to wrap features animations in a vue component. It will inject needed layers and connect the animation with it.
<template>
<slot></slot>
</template>
<script setup lang="ts">
import MyAnimation from "./my-animation";
import useAnimation from "@/composables/useAnimation";
const props = withDefaults(
defineProps<{
speed?: number;
// ...
}>(),
{
speed: 0,
},
);
const exposed = useAnimation(MyAnimation, props);
defineExpose(exposed);
</script>
MapControl Plugins
The composable useControl
can and should be used to wrap features map controls in a vue component. It handles adding / removing a control to the map or a control bar.
<template>
<div v-if="false"></div>
</template>
<script setup lang="ts">
import { useAttrs } from "vue";
import useControl from "@/composables/useControl";
import MyControl from "./my-control";
const props = withDefaults(
defineProps<{
className?: string;
// ...
}>(),
{
className: "ol-my-control",
},
);
const attrs = useAttrs();
const { control } = useControl(MyControl, props, attrs);
defineExpose({
control,
});
</script>
Geometry Plugins
The composable useGeometry
can and should be used to wrap geometries in a vue component. It injects the parent feature component and applies a geometry. It also watches for geometry changes and updates the features.
<template>
<div v-if="false"></div>
</template>
<script setup lang="ts">
import MyGeometry from "./my-geometry";
import useGeometry from "@/composables/useGeometry";
const props = withDefaults(
defineProps<{
someProperty: number[];
}>(),
{},
);
const geometry = useGeometry(MyGeometry, props);
defineExpose({
geometry,
});
</script>
Other Composables
The following composables are exposed to support 3rd-party libs.
usePropsAsObjectProperties
This composable is used to proxy vue component props and:
- log them in debug mode
- make them reactive
- convert prop
styles
intstyle
sincestyle
cannot be used as HTML attribute since it conflicts wit nativestyle
attribute.
const props = withDefaults(defineProps<{
title: string;
styles: string[]
}>(), {
styles: []
});
const properties = usePropsAsObjectProperties(props);
// properties.styles is undefined
// properties.style is of type string[]
useOpenLayersEvents
This composable is used to be able to pass-through all original events to the current component.
// ...
import { useOpenLayersEvents } from "@/composables/useOpenLayersEvents";
// prevent warnings caused by event pass-through via useOpenLayersEvents composable
defineOptions({
inheritAttrs: false,
});
useOpenLayersEvents(draw, ["drawstart", "drawend"]);