Skip to content

Commit 8846176

Browse files
committed
feat(ol-interaction-mouse-wheel-zoom): provide new interaction to disable / customize mouse zoom behavior
closes #356
1 parent cf67e75 commit 8846176

16 files changed

+201
-26
lines changed

docs/.vitepress/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ export const config: UserConfig = {
384384
text: "ol-interaction-modify",
385385
link: "/componentsguide/interactions/modify/",
386386
},
387+
{
388+
text: "ol-interaction-mouse-wheel-zoom",
389+
link: "/componentsguide/interactions/mousewheelzoom/",
390+
},
387391
{
388392
text: "ol-interaction-pointer",
389393
link: "/componentsguide/interactions/pointer/",

docs/componentsguide/animations.plugin.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import { createApp } from "vue";
1010
import App from "./App.vue";
1111

1212
import {
13-
// [!code focus:6]
1413
Map,
1514
Layers,
1615
Sources,
17-
Animations,
16+
Animations,// [!code focus]
1817
} from "vue3-openlayers";
1918

2019
const app = createApp(App);

docs/componentsguide/geometries.plugin.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import { createApp } from "vue";
1010
import App from "./App.vue";
1111

1212
import {
13-
// [!code focus:6]
1413
Map,
1514
Layers,
1615
Sources,
17-
Geometries,
16+
Geometries,// [!code focus]
1817
} from "vue3-openlayers";
1918

2019
const app = createApp(App);

docs/componentsguide/interactions.plugin.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import { createApp } from "vue";
1010
import App from "./App.vue";
1111

1212
import {
13-
// [!code focus:6]
1413
Map,
1514
Layers,
1615
Sources,
17-
Interactions,
16+
Interactions,// [!code focus]
1817
} from "vue3-openlayers";
1918

2019
const app = createApp(App);
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# ol-interaction-mouse-wheel-zoom
2+
3+
> Define the mouse wheel zoom behaviour
4+
5+
[[toc]]
6+
7+
## Demo
8+
9+
<script setup>
10+
import MouseWheelZoomDemo from "@demos/MouseWheelZoomDemo.vue"
11+
</script>
12+
13+
<ClientOnly>
14+
<MouseWheelZoomDemo/>
15+
</ClientOnly>
16+
17+
## Setup
18+
19+
<!--@include: ../../interactions.plugin.md-->
20+
21+
## Usage
22+
23+
| Plugin Usage | Explicit Import |
24+
|-------------------------------------|:--------------------------------------------:|
25+
| `<ol-interaction-mouse-wheel-zoom>` | `<Interactions.OlInteractionMouseWheelZoom>` |
26+
27+
::: code-group
28+
29+
<<< ../../../../src/demos/MouseWheelZoomDemo.vue
30+
31+
:::
32+
33+
## Properties
34+
35+
### Props from OpenLayers
36+
37+
Properties are passed-trough from OpenLayers directly.
38+
Their types and default values can be checked-out [in the official OpenLayers docs](https://openlayers.org/en/latest/apidoc/module-ol_interaction_MouseWheelZoom.html).
39+
Only some properties deviate caused by reserved keywords from Vue / HTML.
40+
This deviating props are described in the section below.
41+
42+
### Deviating Properties
43+
44+
None.
45+
46+
## Events
47+
48+
You have access to all Events from the underlying interaction.
49+
Check out [the official OpenLayers docs](https://openlayers.org/en/latest/apidoc/module-ol_interaction_MouseWheelZoom.html) to see the available events tht will be fired.
50+
51+
```html
52+
<ol-interaction-mouse-wheel-zoom @error="handleEvent" />
53+
```
54+
55+
## Methods
56+
57+
You have access to all Methods from the underlying interaction.
58+
Check out [the official OpenLayers docs](https://openlayers.org/en/latest/apidoc/module-ol_interaction_MouseWheelZoom.html) to see the available methods.
59+
60+
To access the source, you can use a `ref()` as shown below:
61+
62+
```vue
63+
<template>
64+
<!-- ... -->
65+
<ol-interaction-mouse-wheel-zoom ref="interactionRef" />
66+
<!-- ... -->
67+
</template>
68+
69+
<script setup lang="ts">
70+
import { ref, onMounted } from "vue";
71+
import type MouseWheelZoom from "ol/interaction/MouseWheelZoom";
72+
73+
const interactionRef = ref<{ mouseWheelZoom: MouseWheelZoom } | null>(null);
74+
75+
onMounted(() => {
76+
const mouseWheelZoom: MouseWheelZoom = interactionRef.value?.mouseWheelZoom;
77+
// call your method on `mouseWheelZoom`
78+
});
79+
</script>
80+
```
81+
82+

docs/componentsguide/layers.plugin.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import { createApp } from "vue";
1010
import App from "./App.vue";
1111

1212
import {
13-
// [!code focus:6]
1413
Map,
15-
Layers,
14+
Layers,// [!code focus]
1615
Sources,
1716
} from "vue3-openlayers";
1817

docs/componentsguide/map.plugin.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import { createApp } from "vue";
1010
import App from "./App.vue";
1111

1212
import {
13-
// [!code focus:5]
14-
Map,
13+
Map,// [!code focus]
1514
Layers,
1615
Sources,
1716
} from "vue3-openlayers";

docs/componentsguide/mapcontrols.plugin.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import { createApp } from "vue";
1010
import App from "./App.vue";
1111

1212
import {
13-
// [!code focus:6]
1413
Map,
1514
Layers,
1615
Sources,
17-
MapControls,
16+
MapControls,// [!code focus]
1817
} from "vue3-openlayers";
1918

2019
const app = createApp(App);

docs/componentsguide/sources.plugin.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ import { createApp } from "vue";
1010
import App from "./App.vue";
1111

1212
import {
13-
// [!code focus:6]
1413
Map,
1514
Layers,
16-
Sources,
15+
Sources,// [!code focus]
1716
} from "vue3-openlayers";
1817

1918
const app = createApp(App);

docs/componentsguide/styles.plugin.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import { createApp } from "vue";
1010
import App from "./App.vue";
1111

1212
import {
13-
// [!code focus:6]
1413
Map,
1514
Layers,
1615
Sources,
17-
Styles,
16+
Styles,// [!code focus]
1817
} from "vue3-openlayers";
1918

2019
const app = createApp(App);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<template>
2+
<slot></slot>
3+
</template>
4+
5+
<script setup lang="ts">
6+
import { inject, watch, onMounted, onUnmounted, computed } from "vue";
7+
import MouseWheelZoom, { type Options } from "ol/interaction/MouseWheelZoom";
8+
import type Map from "ol/Map";
9+
import usePropsAsObjectProperties from "@/composables/usePropsAsObjectProperties";
10+
11+
const props = withDefaults(defineProps<Options>(), {
12+
onFocusOnly: false,
13+
maxDelta: 1,
14+
duration: 250,
15+
timeout: 80,
16+
useAnchor: true,
17+
constrainResolution: false,
18+
});
19+
20+
const map = inject<Map>("map");
21+
const properties = usePropsAsObjectProperties(props);
22+
const mouseWheelZoom = computed(() => new MouseWheelZoom(properties));
23+
24+
watch(mouseWheelZoom, (newVal, oldVal) => {
25+
map?.removeInteraction(oldVal);
26+
map?.addInteraction(newVal);
27+
map?.changed();
28+
});
29+
30+
onMounted(() => {
31+
// remove the default MouseWheelZoom interaction if available
32+
map?.getInteractions().forEach((interaction) => {
33+
if (interaction instanceof MouseWheelZoom) {
34+
map?.removeInteraction(interaction);
35+
}
36+
});
37+
map?.addInteraction(mouseWheelZoom.value);
38+
});
39+
40+
onUnmounted(() => {
41+
map?.removeInteraction(mouseWheelZoom.value);
42+
});
43+
44+
defineExpose({
45+
mouseWheelZoom,
46+
});
47+
</script>

src/components/interaction/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import OlInteractionModify from "./OlInteractionModify.vue";
1010
import OlInteractionPointer from "./OlInteractionPointer.vue";
1111
import OlInteractionSnap from "./OlInteractionSnap.vue";
1212
import OlInteractionTransform from "./OlInteractionTransform.vue";
13+
import OlInteractionMouseWheelZoom from "./OlInteractionMouseWheelZoom.vue";
1314
import type { Vue3OpenlayersGlobalOptions } from "@/types";
1415

1516
function install(app: App, options?: Vue3OpenlayersGlobalOptions) {
@@ -24,6 +25,7 @@ function install(app: App, options?: Vue3OpenlayersGlobalOptions) {
2425
app.component("OlInteractionPointer", OlInteractionPointer);
2526
app.component("OlInteractionSnap", OlInteractionSnap);
2627
app.component("OlInteractionTransform", OlInteractionTransform);
28+
app.component("OlInteractionMouseWheelZoom", OlInteractionMouseWheelZoom);
2729

2830
if (options) {
2931
app.provide("ol-options", options);
@@ -49,4 +51,5 @@ export {
4951
OlInteractionPointer,
5052
OlInteractionSnap,
5153
OlInteractionTransform,
54+
OlInteractionMouseWheelZoom,
5255
};

src/demos/MouseWheelZoomDemo.vue

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<template>
2+
Zoom is only active when the platform-modifier-key (the meta-key on Mac,
3+
ctrl-key otherwise) is pressed (no additional key e. g. shift-key) .
4+
<ol-map
5+
:loadTilesWhileAnimating="true"
6+
:loadTilesWhileInteracting="true"
7+
style="height: 400px"
8+
>
9+
<ol-view
10+
ref="view"
11+
:center="center"
12+
:zoom="zoom"
13+
:projection="projection"
14+
/>
15+
16+
<ol-tile-layer>
17+
<ol-source-osm />
18+
</ol-tile-layer>
19+
20+
<ol-interaction-mouse-wheel-zoom :condition="condition" />
21+
</ol-map>
22+
</template>
23+
24+
<script setup>
25+
import { ref } from "vue";
26+
import { platformModifierKeyOnly } from "ol/events/condition";
27+
28+
const center = ref([-102.13121, 40.2436]);
29+
const projection = ref("EPSG:4326");
30+
const zoom = ref(5);
31+
const condition = ref(platformModifierKeyOnly);
32+
</script>

tests/MapPage.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { expect, Locator, Page } from "@playwright/test";
22

33
type Point = [x: number, y: number];
44

5+
type Modifier = "Alt" | "Control" | "Meta" | "ControlOrMeta" | "Shift";
6+
57
export class MapPage {
68
readonly getStartedLink: Locator;
79
readonly gettingStartedHeader: Locator;
@@ -43,6 +45,14 @@ export class MapPage {
4345
}
4446
}
4547

48+
async zoomWithMouseWheel(deltaY = 5, modifier?: Modifier) {
49+
const boundingBox = await this.canvasBBox();
50+
await this.page.mouse.move(boundingBox.x + 100, boundingBox.y + 100);
51+
await this.page.keyboard.down(modifier);
52+
await this.page.mouse.wheel(0, -deltaY);
53+
await this.page.keyboard.up(modifier);
54+
}
55+
4656
async checkCanvasScreenshot() {
4757
await expect(this.mapCanvas()).toHaveScreenshot({
4858
timeout: 8000,
@@ -53,11 +63,7 @@ export class MapPage {
5363
return await this.mapCanvas().boundingBox();
5464
}
5565

56-
async dragOnCanvas(
57-
start: Point,
58-
end: Point,
59-
modifiers?: ("Alt" | "Control" | "Meta" | "Shift")[],
60-
) {
66+
async dragOnCanvas(start: Point, end: Point, modifiers?: Modifier[]) {
6167
const boundingBox = await this.canvasBBox();
6268

6369
if (boundingBox) {
@@ -105,11 +111,7 @@ export class MapPage {
105111
}
106112
}
107113

108-
async clickOnCanvas(
109-
point: Point,
110-
modifiers?: ("Alt" | "Control" | "Meta" | "Shift")[],
111-
dblClick = false,
112-
) {
114+
async clickOnCanvas(point: Point, modifiers?: Modifier[], dblClick = false) {
113115
dblClick
114116
? await this.mapCanvas().dblclick({
115117
position: {

tests/interactions.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,19 @@ test.describe("ol-interaction-dragrotatezoom", () => {
107107
});
108108
});
109109

110+
test.describe("ol-interaction-mouse-wheel-zoom", () => {
111+
test("should zoom the map view when platform modifier key pressed", async ({
112+
page,
113+
}) => {
114+
const map = new MapPage(page);
115+
await map.goto("/componentsguide/interactions/mousewheelzoom/");
116+
await map.waitUntilReady();
117+
await map.waitUntilCanvasLoaded();
118+
await map.zoomWithMouseWheel(100, "ControlOrMeta");
119+
await map.checkCanvasScreenshot();
120+
});
121+
});
122+
110123
test.describe("ol-interaction-link", () => {
111124
test("should update the URL after loading", async ({ page }) => {
112125
const map = new MapPage(page);

0 commit comments

Comments
 (0)