Skip to content

Commit

Permalink
feat(ol-interaction-link): add interaction for sync with URL query pa…
Browse files Browse the repository at this point in the history
…rams
  • Loading branch information
d-koppenhagen committed Apr 4, 2024
1 parent e72b1f9 commit 4fdd742
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 45 deletions.
88 changes: 46 additions & 42 deletions docs/.vitepress/config.ts
Expand Up @@ -259,48 +259,6 @@ export const config: UserConfig = {
},
],
},
{
text: "Interactions",
collapsed: true,
items: [
{
text: "ol-interaction-clusterselect",
link: "/componentsguide/interactions/clusterselect/",
},
{
text: "ol-interaction-draw",
link: "/componentsguide/interactions/draw/",
},
{
text: "ol-interaction-dragbox",
link: "/componentsguide/interactions/dragbox/",
},
{
text: "ol-interaction-dragrotate",
link: "/componentsguide/interactions/dragrotate/",
},
{
text: "ol-interaction-dragrotatezoom",
link: "/componentsguide/interactions/dragrotatezoom/",
},
{
text: "ol-interaction-modify",
link: "/componentsguide/interactions/modify/",
},
{
text: "ol-interaction-select",
link: "/componentsguide/interactions/select/",
},
{
text: "ol-interaction-snap",
link: "/componentsguide/interactions/snap/",
},
{
text: "ol-interaction-transform",
link: "/componentsguide/interactions/transform/",
},
],
},
{
text: "Animations",
collapsed: true,
Expand Down Expand Up @@ -337,6 +295,52 @@ export const config: UserConfig = {
},
],
},
{
text: "Interactions",
collapsed: true,
items: [
{
text: "ol-interaction-clusterselect",
link: "/componentsguide/interactions/clusterselect/",
},
{
text: "ol-interaction-draw",
link: "/componentsguide/interactions/draw/",
},
{
text: "ol-interaction-dragbox",
link: "/componentsguide/interactions/dragbox/",
},
{
text: "ol-interaction-dragrotate",
link: "/componentsguide/interactions/dragrotate/",
},
{
text: "ol-interaction-dragrotatezoom",
link: "/componentsguide/interactions/dragrotatezoom/",
},
{
text: "ol-interaction-link",
link: "/componentsguide/interactions/link/",
},
{
text: "ol-interaction-modify",
link: "/componentsguide/interactions/modify/",
},
{
text: "ol-interaction-select",
link: "/componentsguide/interactions/select/",
},
{
text: "ol-interaction-snap",
link: "/componentsguide/interactions/snap/",
},
{
text: "ol-interaction-transform",
link: "/componentsguide/interactions/transform/",
},
],
},
{
text: "Map Controls",
collapsed: true,
Expand Down
71 changes: 71 additions & 0 deletions docs/componentsguide/interactions/link/index.md
@@ -0,0 +1,71 @@
# ol-interaction-link

The link interaction allows you to synchronize the map state with the URL.
By default the view center, zoom level, and rotation will be reflected in the URL as you navigate around the map.
Layer visibility is also reflected in the URL.
Reloading the page restores the map view state.

<script setup>
import ViewDemo from "@demos/ViewDemo.vue"
</script>

<ClientOnly>
<ViewDemo/>
</ClientOnly>

## Usage

::: code-group

<<< ../../../../src/demos/ViewDemo.vue

:::

## 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](https://openlayers.org/en/latest/apidoc/module-ol_interaction_Link-Link.html).
Only some properties deviate caused by reserved keywords from Vue / HTML.
This deviating props are described in the section below.

### Deviating Properties

None.

## Events

You have access to all Events from the underlying interaction.
Check out [the official OpenLayers docs](https://openlayers.org/en/latest/apidoc/module-ol_interaction_Link-Link.html) to see the available events tht will be fired.

```html
<ol-interaction-link @error="handleEvent" />
```

## Methods

You have access to all Methods from the underlying interaction.
Check out [the official OpenLayers docs](https://openlayers.org/en/latest/apidoc/module-ol_interaction_Link-Link.html) to see the available methods.

To access the source, you can use a `ref()` as shown below:

```vue
<template>
<!-- ... -->
<ol-interaction-link ref="interactionRef" />
<!-- ... -->
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import type Link from "ol/interaction/Link";
const interactionRef = ref<{ link: Link } | null>(null);
onMounted(() => {
const link: Link = interactionRef.value?.link;
// call your method on `link`
});
</script>
```
57 changes: 57 additions & 0 deletions src/components/interaction/OlLinktInteraction.vue
@@ -0,0 +1,57 @@
<template>
<slot></slot>
</template>

<script setup lang="ts">
import {
provide,
inject,
watch,
onMounted,
onUnmounted,
shallowRef,
} from "vue";
import Link, { type Options } from "ol/interaction/Link";
import type Map from "ol/Map";
import usePropsAsObjectProperties from "@/composables/usePropsAsObjectProperties";
import { useOpenLayersEvents } from "@/composables/useOpenLayersEvents";
// prevent warnings caused by event pass-through via useOpenLayersEvents composable
defineOptions({
inheritAttrs: false,
});
const props = withDefaults(defineProps<Options>(), {
animate: true,
params: ["x", "y", "z", "r", "l"],
replace: false,
prefix: "",
});
const map = inject<Map>("map");
const { properties } = usePropsAsObjectProperties(props);
const link = shallowRef(new Link(properties));
useOpenLayersEvents(link, ["change:active"]);
watch(link, (newVal, oldVal) => {
map?.removeInteraction(oldVal);
map?.addInteraction(newVal);
map?.changed();
});
onMounted(() => {
map?.addInteraction(link.value);
});
onUnmounted(() => {
map?.removeInteraction(link.value);
});
provide("stylable", link);
defineExpose({
link,
});
</script>
3 changes: 3 additions & 0 deletions src/components/interaction/index.ts
Expand Up @@ -3,6 +3,7 @@ import OlClusterSelectInteraction from "./OlClusterSelectInteraction.vue";
import OlDragBoxInteraction from "./OlDragBoxInteraction.vue";
import OlDragRotateInteraction from "./OlDragRotateInteraction.vue";
import OlDragRotateZoomInteraction from "./OlDragRotateZoomInteraction.vue";
import OlLinktInteraction from "./OlLinktInteraction.vue";
import OlSelectInteraction from "./OlSelectInteraction.vue";
import OlDrawInteraction from "./OlDrawInteraction.vue";
import OlModifyInteraction from "./OlModifyInteraction.vue";
Expand All @@ -14,6 +15,7 @@ function install(app: App) {
app.component("ol-interaction-dragbox", OlDragBoxInteraction);
app.component("ol-interaction-dragrotate", OlDragRotateInteraction);
app.component("ol-interaction-dragrotatezoom", OlDragRotateZoomInteraction);
app.component("ol-interaction-link", OlLinktInteraction);
app.component("ol-interaction-select", OlSelectInteraction);
app.component("ol-interaction-draw", OlDrawInteraction);
app.component("ol-interaction-modify", OlModifyInteraction);
Expand All @@ -29,6 +31,7 @@ export {
OlDragBoxInteraction,
OlDragRotateInteraction,
OlDragRotateZoomInteraction,
OlLinktInteraction,
OlSelectInteraction,
OlDrawInteraction,
OlModifyInteraction,
Expand Down
2 changes: 1 addition & 1 deletion src/demos/AnimatedClusterDemo2.vue
Expand Up @@ -94,7 +94,7 @@ const geoJsonFeatures = computed(() => {
return geoJson.readFeatures(providerFeatureCollection);
});
const overrideStyleFunction = (feature: FeatureLike, style: any) => {
const overrideStyleFunction = (feature: FeatureLike, style) => {
const clusteredFeatures = feature.get("features");
const size = clusteredFeatures.length;
Expand Down
1 change: 1 addition & 0 deletions src/demos/ViewDemo.vue
Expand Up @@ -21,6 +21,7 @@
</ol-tile-layer>

<ol-rotate-control></ol-rotate-control>
<ol-interaction-link />
</ol-map>

<ul>
Expand Down
2 changes: 1 addition & 1 deletion src/demos/points.ts
Expand Up @@ -503,6 +503,6 @@ export const arrayWith500Points = [

export const arrayWith50000Points = Array(100)
.fill()
.reduce((acc, _) => acc.concat(arrayWith500Points), []);
.reduce((acc) => acc.concat(arrayWith500Points), []);

console.log(arrayWith50000Points);
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 36 additions & 1 deletion tests/interactions.test.ts
@@ -1,4 +1,4 @@
import { test } from "@playwright/test";
import { expect, test } from "@playwright/test";

import { MapPage } from "./MapPage";

Expand Down Expand Up @@ -107,6 +107,41 @@ test.describe("ol-interaction-dragrotatezoom", () => {
});
});

test.describe("ol-interaction-link", () => {
test("should update the URL after loading", async ({ page }) => {
const map = new MapPage(page);
await map.goto("/componentsguide/interactions/link/");
await map.waitUntilReady();
await map.waitUntilCanvasLoaded();
await map.checkCanvasScreenshot();
await expect(map.page).toHaveURL(
"/componentsguide/interactions/link/?x=40&y=40&z=8&r=0&l=1",
);
});

test("should load map view based on query params", async ({ page }) => {
const map = new MapPage(page);
await map.goto(
"/componentsguide/interactions/link/?x=13.3&y=52.5&z=9&r=-0.1&l=1",
);
await map.waitUntilReady();
await map.waitUntilCanvasLoaded();
await map.checkCanvasScreenshot();
});

test("should no override existing query params by default", async ({
page,
}) => {
const map = new MapPage(page);
await map.goto("/componentsguide/interactions/link/?existingParam=active");
await map.waitUntilReady();
await map.waitUntilCanvasLoaded();
await expect(map.page).toHaveURL(
"/componentsguide/interactions/link/?existingParam=active&x=40&y=40&z=8&r=0&l=1",
);
});
});

test.describe("ol-interaction-select", () => {
test("should be able to select a shape by hover", async ({ page }) => {
const map = new MapPage(page);
Expand Down
1 change: 1 addition & 0 deletions vite.config.ts
Expand Up @@ -122,6 +122,7 @@ export default defineConfig({
"ol/geom/Point": "Point$2",
"ol/geom/Polygon": "Polygon",
"ol/style/Style": "Style",
"ol/interaction/Link": "Link",
"ol/interaction/Draw": "Draw",
"ol/interaction/DragBox": "DragBox",
"ol/interaction/Modify": "Modify",
Expand Down

0 comments on commit 4fdd742

Please sign in to comment.