ol-overlay
HTML element attached to geographical coordinate
ol-overlay
component creates a HTML element that would be displayed over the map. It has default scoped slot to render your custom content.
Setup
Plugin usage
This component is part of the Map
plugin. If not installed globally, you need to import and use
the plugin in your main.ts
or use the explicit component import (see section below).
Import and use the Map
plugin
import { createApp } from "vue";
import App from "./App.vue";
import {
Map,
Layers,
Sources,
} from "vue3-openlayers";
const app = createApp(App);
// ...
app.use(Map);
// ...
2
3
4
5
6
7
8
9
10
11
12
13
Explicit import
If you don't want to install a plugin, you can import the component explicitly. It's available as a child of the named export Map
.
NOTE
The following documentation refers to the plugin usage. Please make sure to adopt the component names, when you decided to use explicit component imports (e. g. <ol-map>
becomes <Map.OlMap>
etc.).
Usage
Plugin Usage | Explicit Import |
---|---|
<ol-overlay> | <Map.OlOverlay> |
Example 1: Overlay Content
Example below shows how to add custom content on to the map.
<template>
<button class="btn-default" type="button" @click="moveToEast">
Move to the right
</button>
<ol-map style="height: 400px">
<ol-view
ref="view"
:center="center"
:zoom="zoom"
:projection="projection"
/>
<ol-tile-layer>
<ol-source-osm />
</ol-tile-layer>
<ol-overlay
:position="[item + 37.9 + offset, 40.1]"
v-for="item in list"
:key="item"
:autoPan="true"
>
<div class="overlay-content">
{{ item }}
</div>
</ol-overlay>
</ol-map>
</template>
<script setup>
import { ref } from "vue";
const center = ref([40, 40]);
const projection = ref("EPSG:4326");
const zoom = ref(8);
const offset = ref(0);
const list = ref([2, 1, 3, 5, -1]);
function moveToEast() {
offset.value += 0.1;
}
</script>
<style scoped>
.overlay-content {
background: #efefef;
box-shadow: 0 5px 10px rgb(2 2 2 / 20%);
padding: 10px 20px;
font-size: 16px;
color: black;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Example 2: Measure Distance
<template>
<ol-map
ref="mapRef"
:loadTilesWhileAnimating="true"
:loadTilesWhileInteracting="true"
style="height: 400px"
>
<ol-view ref="view" :center="[-11000000, 4600000]" :zoom="15" />
<ol-tile-layer>
<ol-source-osm />
</ol-tile-layer>
<ol-overlay
v-if="tooltipCoord"
:position="tooltipCoord"
:offset="[0, -15]"
positioning="bottom-center"
:stopEvent="false"
:insertFirst="false"
>
<div class="tooltip tooltip-measure">
{{ tooltipText }}
</div>
</ol-overlay>
<ol-overlay
v-if="helpTooltipCoord"
:position="helpTooltipCoord"
:offset="[0, 15]"
positioning="top-center"
>
<div class="tooltip tooltip-info">
{{ helpTooltipText }}
</div>
</ol-overlay>
<ol-vector-layer>
<ol-source-vector>
<ol-interaction-draw
:type="drawType"
@drawend="drawend"
@drawstart="drawstart"
/>
</ol-source-vector>
<ol-style>
<ol-style-stroke color="#ffcc33" :width="2" />
<ol-style-fill color="rgba(255, 255, 255, 0.2)" />
<ol-style-circle :radius="7">
<ol-style-fill color="#ffcc33" />
</ol-style-circle>
</ol-style>
</ol-vector-layer>
</ol-map>
</template>
<script setup lang="ts">
import { Feature, Map, type MapBrowserEvent } from "ol";
import { LineString } from "ol/geom";
import { type DrawEvent } from "ol/interaction/Draw";
import { onMounted, ref } from "vue";
import { getLength } from "ol/sphere";
import type { EventsKey } from "ol/events";
import type { Coordinate } from "ol/coordinate";
import { unByKey } from "ol/Observable";
const mapRef = ref<{ map: Map } | null>(null);
const drawType = ref("LineString");
const sketch = ref<Feature | null>(null);
const tooltipCoord = ref<Coordinate | null>(null);
const tooltipText = ref("");
const helpTooltipCoord = ref<Coordinate | null>(null);
const helpTooltipText = ref("");
let listener: EventsKey;
const continueLineMsg = "Click to continue drawing the line";
function drawstart(evt: DrawEvent) {
sketch.value = evt.feature;
const geom = sketch.value.getGeometry();
if (geom instanceof LineString) {
tooltipCoord.value = geom.getLastCoordinate();
listener = geom.on("change", function (evt) {
const geom = evt.target;
if (geom instanceof LineString) {
tooltipText.value = formatLength(geom);
tooltipCoord.value = geom.getLastCoordinate();
}
});
}
}
function drawend() {
// remove drawn sketch
sketch.value = null;
// unset tooltip so that a new one can be created
tooltipCoord.value = null;
tooltipText.value = "";
// cleanup listeners
unByKey(listener);
}
function showHelpInfoOnPointermove(evt: MapBrowserEvent<PointerEvent>) {
if (evt.dragging) {
return;
}
let helpMsg = "Click to start drawing";
const geom = sketch.value?.getGeometry();
if (geom instanceof LineString) {
helpMsg = continueLineMsg;
}
helpTooltipText.value = helpMsg;
helpTooltipCoord.value = evt.coordinate;
}
function formatLength(line: LineString) {
const length = getLength(line);
let output = "";
if (length > 100) {
output = Math.round((length / 1000) * 100) / 100 + " " + "km";
} else {
output = Math.round(length * 100) / 100 + " " + "m";
}
return output;
}
onMounted(() => {
mapRef.value?.map.on("pointermove", showHelpInfoOnPointermove);
mapRef.value?.map.getViewport().addEventListener("mouseout", function () {
helpTooltipCoord.value = null;
helpTooltipText.value = "";
});
});
</script>
<style scoped>
.tooltip {
position: relative;
background: rgba(0, 0, 0, 0.5);
border-radius: 4px;
color: white;
padding: 4px 8px;
opacity: 0.7;
white-space: nowrap;
font-size: 12px;
cursor: default;
user-select: none;
}
.tooltip-measure {
font-weight: bold;
}
.tooltip-info {
background-color: #ffcc33;
color: black;
border: 1px solid white;
}
.tooltip-measure:before {
border-top: 6px solid rgba(0, 0, 0, 0.5);
border-right: 6px solid transparent;
border-left: 6px solid transparent;
content: "";
position: absolute;
bottom: -6px;
margin-left: -7px;
left: 50%;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
Properties
Props from OpenLayers
Properties are passed-trough from OpenLayers directly. Their types and default values can be checked-out in the official OpenLayers docs. Only some properties deviate caused by reserved keywords from Vue / HTML. This deviating props are described in the section below.
Deviating Properties
element
The property element
from OpenLayers is filled by the vue components template ref. However, you are still able to override it and bind the component to another differing HTML element.
Events
You have access to all Events from the underlying source. Check out the official OpenLayers docs to see the available events tht will be fired.
<ol-overlay @error="handleEvent">My Overlay Text</ol-overlay>
Methods
You have access to all Methods from the underlying source. Check out the official OpenLayers docs to see the available methods.
To access the source, you can use a ref()
as shown below:
<template>
<!-- ... -->
<ol-overlay ref="overlayRef">My Overlay Text</ol-overlay>
<!-- ... -->
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type Overlay from "ol/Overlay";
const overlayRef = ref<{ overlay: Overlay }>(null);
onMounted(() => {
const overlay: Overlay = overlayRef.value?.overlay;
// call your method on `overlay`
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17