Skip to content

Commit 3eb1fff

Browse files
committed
feat(ol-interaction-dragbox): add DragBox component wrapper
closes #307
1 parent f51cd25 commit 3eb1fff

File tree

11 files changed

+179
-9
lines changed

11 files changed

+179
-9
lines changed

docs/.vitepress/config.ts

+4
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ export const config: UserConfig = {
271271
text: "ol-interaction-draw",
272272
link: "/componentsguide/interactions/draw/",
273273
},
274+
{
275+
text: "ol-interaction-dragbox",
276+
link: "/componentsguide/interactions/dragbox/",
277+
},
274278
{
275279
text: "ol-interaction-dragrotate",
276280
link: "/componentsguide/interactions/dragrotate/",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# ol-interaction-dragbox
2+
3+
> Allows the user to draw a vector box by clicking and dragging on the map,
4+
> normally combined with a _condition_ that limits it to when the `shift` or other key is held down.
5+
6+
<script setup>
7+
import VectorSourceDemo1 from "@demos/VectorSourceDemo1.vue"
8+
</script>
9+
10+
<ClientOnly>
11+
<VectorSourceDemo1/>
12+
</ClientOnly>
13+
14+
## Usage
15+
16+
::: code-group
17+
18+
<<< ../../../../src/demos/VectorSourceDemo1.vue
19+
20+
:::
21+
22+
## Properties
23+
24+
### Props from OpenLayers
25+
26+
Properties are passed-trough from OpenLayers directly.
27+
Their types and default values can be checked-out [in the official OpenLayers docs](https://openlayers.org/en/latest/apidoc/module-ol_interaction_DragBox-DragBox.html).
28+
Only some properties deviate caused by reserved keywords from Vue / HTML.
29+
This deviating props are described in the section below.
30+
31+
### Deviating Properties
32+
33+
None.
34+
35+
## Events
36+
37+
You have access to all Events from the underlying interaction.
38+
Check out [the official OpenLayers docs](https://openlayers.org/en/latest/apidoc/module-ol_interaction_DragBox-DragBox.html) to see the available events tht will be fired.
39+
40+
```html
41+
<ol-interaction-dragbox @error="handleEvent">
42+
<!-- ... -->
43+
</ol-interaction-dragbox>
44+
```
45+
46+
## Methods
47+
48+
You have access to all Methods from the underlying interaction.
49+
Check out [the official OpenLayers docs](https://openlayers.org/en/latest/apidoc/module-ol_interaction_DragBox-DragBox.html) to see the available methods.
50+
51+
To access the source, you can use a `ref()` as shown below:
52+
53+
```vue
54+
<template>
55+
<!-- ... -->
56+
<ol-map ref="mapRef" @error="handleEvent">
57+
<!-- ... -->
58+
</ol-map>
59+
<!-- ... -->
60+
</template>
61+
62+
<script setup lang="ts">
63+
import { ref, onMounted } from "vue";
64+
import type DragBox from "ol/interaction/DragBox";
65+
66+
const drgboxRef = ref<{ dragbox: DragBox } | null>(null);
67+
68+
onMounted(() => {
69+
const dragbox: DragBox = drgboxRef.value?.dragbox;
70+
// call your method on `dragbox`
71+
});
72+
</script>
73+
```
74+

docs/componentsguide/map/index.md

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ See also documentation of `ol-view` component.
2525

2626
:::
2727

28+
## Properties
29+
2830
### Props from OpenLayers
2931

3032
Properties are passed-trough from OpenLayers directly.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<template lang="">
2+
<slot></slot>
3+
</template>
4+
5+
<script setup lang="ts">
6+
import { inject, watch, onMounted, onUnmounted, computed } from "vue";
7+
8+
import DragBox, { type Options } from "ol/interaction/DragBox";
9+
10+
import usePropsAsObjectProperties from "@/composables/usePropsAsObjectProperties";
11+
import type { Map } from "ol";
12+
import { useOpenLayersEvents } from "@/composables/useOpenLayersEvents";
13+
14+
// prevent warnings caused by event pass-through via useOpenLayersEvents composable
15+
defineOptions({
16+
inheritAttrs: false,
17+
});
18+
19+
const props = withDefaults(defineProps<Options>(), {});
20+
21+
const map = inject<Map>("map");
22+
23+
const { properties } = usePropsAsObjectProperties(props);
24+
25+
const dragbox = computed(() => {
26+
const s = new DragBox({
27+
...properties,
28+
});
29+
30+
return s;
31+
});
32+
33+
useOpenLayersEvents(dragbox, ["boxcancel", "boxdrag", "boxend", "boxstart"]);
34+
35+
watch(dragbox, (newVal, oldVal) => {
36+
map?.removeInteraction(oldVal);
37+
map?.addInteraction(newVal);
38+
39+
map?.changed();
40+
});
41+
42+
onMounted(() => {
43+
map?.addInteraction(dragbox.value);
44+
});
45+
46+
onUnmounted(() => {
47+
map?.removeInteraction(dragbox.value);
48+
});
49+
50+
defineExpose({
51+
dragbox,
52+
});
53+
</script>

src/components/interaction/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { App } from "vue";
22
import OlClusterSelectInteraction from "./OlClusterSelectInteraction.vue";
3+
import OlDragBoxInteraction from "./OlDragBoxInteraction.vue";
34
import OlDragRotateInteraction from "./OlDragRotateInteraction.vue";
45
import OlDragRotateZoomInteraction from "./OlDragRotateZoomInteraction.vue";
56
import OlSelectInteraction from "./OlSelectInteraction.vue";
@@ -10,6 +11,7 @@ import OlTransformInteraction from "./OlTransformInteraction.vue";
1011

1112
function install(app: App) {
1213
app.component("ol-interaction-clusterselect", OlClusterSelectInteraction);
14+
app.component("ol-interaction-dragbox", OlDragBoxInteraction);
1315
app.component("ol-interaction-dragrotate", OlDragRotateInteraction);
1416
app.component("ol-interaction-dragrotatezoom", OlDragRotateZoomInteraction);
1517
app.component("ol-interaction-select", OlSelectInteraction);
@@ -24,6 +26,7 @@ export default install;
2426
export {
2527
install,
2628
OlClusterSelectInteraction,
29+
OlDragBoxInteraction,
2730
OlDragRotateInteraction,
2831
OlDragRotateZoomInteraction,
2932
OlSelectInteraction,

src/demos/VectorSourceDemo1.vue

+31-9
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,48 @@
99
:center="center"
1010
:zoom="zoom"
1111
:projection="projection"
12+
:constrainRotation="16"
1213
/>
1314

14-
<ol-tile-layer>
15-
<ol-source-osm />
16-
</ol-tile-layer>
17-
18-
<ol-vector-layer>
19-
<ol-source-vector :url="url" :format="geoJson"> </ol-source-vector>
15+
<ol-vector-layer background="#1a2b39" ref="vectorSourceRef">
16+
<ol-source-vector :url="url" :format="geoJson">
17+
<ol-style :overrideStyleFunction="styleFn"></ol-style>
18+
</ol-source-vector>
2019
</ol-vector-layer>
20+
21+
<ol-interaction-dragbox
22+
:condition="shiftKeyOnly"
23+
@boxstart="log('boxstart', $event)"
24+
@boxdrag="log('boxdrag', $event)"
25+
@boxend="log('boxend', $event)"
26+
@boxcancel="log('boxcancel', $event)"
27+
></ol-interaction-dragbox>
2128
</ol-map>
2229
</template>
2330

24-
<script setup>
31+
<script setup lang="ts">
32+
import type { Feature } from "ol";
33+
import { Fill, Style } from "ol/style";
34+
import { shiftKeyOnly } from "ol/events/condition";
2535
import { ref, inject } from "vue";
36+
import type { DragBoxEvent } from "ol/interaction/DragBox";
2637
2738
const center = ref([0, 0]);
2839
const projection = ref("EPSG:4326");
29-
const zoom = ref(3);
30-
40+
const zoom = ref(0);
3141
const url = ref("https://openlayers.org/data/vector/ecoregions.json");
3242
const format = inject("ol-format");
3343
const geoJson = new format.GeoJSON();
44+
45+
function styleFn(feature: Feature) {
46+
return new Style({
47+
fill: new Fill({
48+
color: feature.get("COLOR_BIO") || "#eeeeee",
49+
}),
50+
});
51+
}
52+
53+
function log(eventType: string, event: DragBoxEvent) {
54+
console.log(eventType, event);
55+
}
3456
</script>
Loading
Loading

tests/interactions.test.ts

+11
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ test.describe("ol-interaction-draw", () => {
7070
});
7171
});
7272

73+
test.describe("ol-interaction-dragbox", () => {
74+
test("should drag on the map", async ({ page }) => {
75+
const map = new MapPage(page);
76+
await map.goto("/componentsguide/interactions/dragbox/");
77+
await map.waitUntilReady();
78+
await map.waitUntilCanvasLoaded();
79+
await map.dragOnCanvas([180, 180], [300, 180], ["Shift"]);
80+
await map.checkCanvasScreenshot();
81+
});
82+
});
83+
7384
test.describe("ol-interaction-dragrotate", () => {
7485
test("should rotate the map view by dragging on it with pressed modifiers", async ({
7586
page,

vite.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export default defineConfig({
122122
"ol/geom/Polygon": "Polygon",
123123
"ol/style/Style": "Style",
124124
"ol/interaction/Draw": "Draw",
125+
"ol/interaction/DragBox": "DragBox",
125126
"ol/interaction/Modify": "Modify",
126127
"ol/style/Circle": "CircleStyle",
127128
"ol/style/Fill": "Fill",

0 commit comments

Comments
 (0)