Skip to content

Commit b8d284f

Browse files
committed
docs(ol-map): allow to use an existing OlMap instance
closes #366
1 parent ad179f5 commit b8d284f

File tree

9 files changed

+132
-22
lines changed

9 files changed

+132
-22
lines changed

docs/componentsguide/map/index.md

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,47 @@ component to setup `zoom`, `center`, `projection` and other view related propert
88

99
[[toc]]
1010

11-
## Demo
12-
13-
<script setup>
14-
import ViewDemo from "@demos/ViewDemo.vue"
15-
</script>
16-
17-
<ClientOnly>
18-
<ViewDemo />
19-
</ClientOnly>
20-
2111
## Setup
2212

2313
<!--@include: ../map.plugin.md-->
2414

2515
## Usage
2616

17+
<script setup>
18+
import ViewDemo from "@demos/ViewDemo.vue";
19+
import ExistingMapDemo from "@demos/ExistingMapDemo.vue";
20+
</script>
21+
2722
| Plugin Usage | Explicit Import |
2823
| ------------ | :-------------: |
2924
| `<ol-map>` | `<Map.OlMap>` |
3025

3126
Example of a simple map.
3227
See also documentation of `ol-view` component.
3328

29+
<ClientOnly>
30+
31+
<ViewDemo />
32+
</ClientOnly>
33+
3434
::: code-group
3535

3636
<<< ../../../src/demos/ViewDemo.vue
3737

3838
:::
3939

40+
### re-use existing map
41+
42+
<ClientOnly>
43+
<ExistingMapDemo />
44+
</ClientOnly>
45+
46+
::: code-group
47+
48+
<<< ../../../src/demos/ExistingMapDemo.vue
49+
50+
:::
51+
4052
## Properties
4153

4254
### Props from OpenLayers
@@ -48,7 +60,11 @@ This deviating props are described in the section below.
4860

4961
### Deviating Properties
5062

51-
None.
63+
#### instance
64+
65+
You can re-use an existing [OpenLayers `Map`](https://openlayers.org/en/latest/apidoc/module-ol_Map-Map.html) instance.
66+
This is probably useful if your app already includes OpenLayers or some other library which uses OpenLayers and exposes its instance.
67+
The passed `instance` property must be a valid instance of `ol/Map`.
5268

5369
## Events
5470

src/components/map/OlMap.vue

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
</template>
66

77
<script setup lang="ts">
8-
import { ref, provide, onMounted, onUnmounted, watch } from "vue";
8+
import { onMounted, onUnmounted, provide, ref, watch } from "vue";
99
import type { AtPixelOptions } from "ol/Map";
1010
import Map, { type MapOptions } from "ol/Map";
1111
import type { FeatureLike } from "ol/Feature";
@@ -15,8 +15,9 @@ import type { Pixel } from "ol/pixel";
1515
import type { Source } from "ol/source";
1616
import type { Coordinate } from "ol/coordinate";
1717
import usePropsAsObjectProperties from "@/composables/usePropsAsObjectProperties";
18+
import { mergeProperties } from "@/helpers/properties";
1819
19-
const props = defineProps<MapOptions>();
20+
const props = defineProps<MapOptions & { instance?: Map }>();
2021
2122
const emit = defineEmits([
2223
"change:layerGroup",
@@ -36,21 +37,37 @@ const emit = defineEmits([
3637
"rendercomplete",
3738
]);
3839
39-
const properties = usePropsAsObjectProperties(props);
40+
const properties = usePropsAsObjectProperties({
41+
...props,
42+
instance: undefined,
43+
});
4044
4145
const mapRef = ref<string | HTMLElement | undefined>(undefined);
42-
let map: Map | undefined = new Map(properties);
46+
let map: Map =
47+
props.instance || new Map({ ...properties, instance: undefined });
4348
44-
watch(properties, () => {
45-
map?.setProperties(properties);
46-
});
49+
watch(
50+
properties,
51+
() => {
52+
const p = props.instance
53+
? mergeProperties(properties, props.instance.getProperties())
54+
: properties;
55+
map?.setProperties(p);
56+
},
57+
{ immediate: true },
58+
);
4759
4860
onMounted(() => {
49-
map?.setTarget(mapRef.value);
61+
// bind the map to the component template if not re-using an existing one passed via prop.
62+
if (!props.instance) {
63+
map?.setTarget(mapRef.value);
64+
}
5065
});
5166
5267
onUnmounted(() => {
53-
map?.setTarget(undefined);
68+
if (!props.instance) {
69+
map?.setTarget(undefined);
70+
}
5471
map = undefined;
5572
});
5673

src/demos/ExistingMapDemo.vue

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<template>
2+
<div id="map" class="map" tabindex="0" style="height: 400px; width: 100%" />
3+
<ol-map v-if="mapInstance" :instance="mapInstance">
4+
<ol-zoomslider-control />
5+
</ol-map>
6+
</template>
7+
8+
<script setup lang="ts">
9+
import Map from "ol/Map";
10+
import { View } from "ol";
11+
import TileLayer from "ol/layer/Tile";
12+
import OSM from "ol/source/OSM";
13+
import { onMounted, ref } from "vue";
14+
15+
const mapInstance = ref<Map>();
16+
17+
onMounted(() => {
18+
mapInstance.value = new Map({
19+
layers: [
20+
new TileLayer({
21+
source: new OSM(),
22+
}),
23+
],
24+
target: "map",
25+
view: new View({
26+
center: [40, 40],
27+
zoom: 2,
28+
projection: "EPSG:4326",
29+
}),
30+
});
31+
});
32+
</script>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { describe, expect, it } from "vitest";
2+
import { mergeProperties } from "../properties";
3+
4+
describe("mergeProperties", () => {
5+
it("should merge properties of two objects", () => {
6+
const obj1 = {
7+
foo: "hello",
8+
bar: "world",
9+
baz: undefined,
10+
};
11+
const obj2 = {
12+
foo: undefined,
13+
bar: "world2",
14+
};
15+
expect(mergeProperties(obj1, obj2)).toEqual({
16+
foo: "hello",
17+
bar: "world2",
18+
baz: undefined,
19+
});
20+
});
21+
});

src/helpers/properties.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2+
export function mergeProperties<T extends Record<string, any>>(
3+
existingProperties: T,
4+
newProperties: Partial<T>,
5+
): T {
6+
// Iterate over the keys in the new properties object
7+
for (const key in newProperties) {
8+
if (Object.prototype.hasOwnProperty.call(newProperties, key)) {
9+
// Only override if the property in the new object is not undefined
10+
if (newProperties[key] !== undefined) {
11+
existingProperties[key] = newProperties[key]!;
12+
}
13+
}
14+
}
15+
return existingProperties;
16+
}
-260 KB
Binary file not shown.
236 KB
Loading
83.8 KB
Loading

tests/general.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,16 @@ import { test } from "@playwright/test";
33
import { MapPage } from "./MapPage";
44

55
test.describe("ol-map", () => {
6-
test("should render", async ({ page }) => {
7-
const map = new MapPage(page);
6+
test("should render a new map", async ({ page }) => {
7+
const map = new MapPage(page, 0);
8+
await map.goto("/componentsguide/map/");
9+
await map.waitUntilReady();
10+
await map.waitUntilCanvasLoaded();
11+
await map.checkCanvasScreenshot();
12+
});
13+
14+
test("should render a re-used existing map", async ({ page }) => {
15+
const map = new MapPage(page, 1);
816
await map.goto("/componentsguide/map/");
917
await map.waitUntilReady();
1018
await map.waitUntilCanvasLoaded();

0 commit comments

Comments
 (0)