-
Couldn't load subscription status.
- Fork 146
Description
Describe the bug
"[Vue3-OpenLayers Error] OlInteractionModify: Modify interactions needs either a source or features to work. Please provide either the props 'source' or 'feature' or use the component with an '' component."
While using inside or outside .
However, recent test showed me that, if I wait for the features to be loaded with a v-if on the interaction layer and specifying the source, fixes it... But as soon as don't specify source, same error.
Affected version(s)
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
To Reproduce
Place a in a without specifying any source nor features, or outside even when specifying source.
Expected behavior
No errors.
Desktop (please complete the following information):
- OS: Alpine (docker) hosted by Arch
- Browser: Chromium & Firefox
Additional context
Here's the code used :
OpenLayersMap.vue
<template>
<OlMap ref="mapRef" tabindex="0" id="map" @singleclick="mapClicked" @keydown.escape="clickedPosition = [NaN, NaN]">
<OlView :center="center" :zoom="zoom" :maxZoom="props.maxZoom" projection="EPSG:4326" />
<OlTileLayer>
<OlSourceXyz url="https://tile.openstreetmap.org/{z}/{x}/{y}.png" />
</OlTileLayer>
<OlVectorLayer :zIndex="2">
<OlSourceVector ref="vectorSourceRef">
<MapMarker v-for="marker in markerList" :position="marker.position" :marker-id="marker.markerId"
:scale="marker.scale" :key="marker.markerId" />
<OlInteractionModify v-if="markerLoaded" :source="vectorSource" />
</OlSourceVector>
</OlVectorLayer>
<AdditionPopup v-if="!isNaN(clickedPosition[0]) && !isNaN(clickedPosition[1])"
:clicked-position="clickedPosition" />
<!-- <OlInteractionPointer @drag="isMarkerClicked" /> -->
</OlMap>
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref } from 'vue';
import AdditionPopup from './PopUps/AdditionPopup.vue';
import MapMarker from './MapMarker.vue';
// import store from '@/store';
import eventListener from '@/technicals/eventBus';
// import OlInteractionModify from 'vue3-openlayers';
// props
const props = defineProps({
startPosition: {
type: Array,
default: () => [51.505, -0.09] // Default to London coordinates
},
startZoom: {
type: Number,
default: () => 13
},
maxZoom: {
type: Number,
default: () => 19
}
});
// data
//// Template refs
const mapRef = ref("mapRef");
const vectorSourceRef = ref('vectorSourceRef');
//// Data properties
const markerLoaded = ref(false);
const center = ref(props.startPosition);
const zoom = ref(props.startZoom)
const markerList = ref([
{
position: [center.value[0], center.value[1]],
markerId: 'marker1',
scale: 2
},
{
position: [center.value[0] + 0.002, center.value[1] + 0.0003],
markerId: 'marker2'
}
]);
const clickedPosition = ref([NaN, NaN]);
// computed
const map = computed(() => mapRef.value ? mapRef.value.map : null);
const vectorSource = computed(() => vectorSourceRef.value ? vectorSourceRef.value.source : null);
const features = computed(() => vectorSource.value ? vectorSource.value.getFeatures() : []);
// lifecycle hooks
onMounted(() => {
console.log("Map mounted:", map.value);
eventListener.$on('closePopup', popupClosed);
eventListener.$on('addMarker', addMarker);
markerLoaded.value = true;
console.log("vectorSource:", vectorSourceRef.value.source);
console.log("vectorSource:", vectorSourceRef.value.source.getFeatures());
});
onUnmounted(() => {
eventListener.$off('closePopup');
});
// methods
function popupClosed() {
clickedPosition.value = [NaN, NaN];
}
function mapClicked(event) {
console.log("Map clicked at:", event.coordinate);
console.log("features on map:", vectorSource.value.getFeatures());
const hasFeature = map.value.hasFeatureAtPixel(event.pixel);
if (hasFeature) {
map.value.forEachFeatureAtPixel(event.pixel, (feature) => {
feature.dispatchEvent('click');
});
} else {
// If no feature is clicked, we set the clicked position
clickedPosition.value = event.coordinate;
}
}
//
function isMarkerClicked(event) {
const hasFeature = map.value.hasFeatureAtPixel(event.pixel);
console.log("Has feature at pixel:", hasFeature);
}
function addMarker() {
console.log("Adding marker at position:", clickedPosition.value);
}
</script>
<style scoped>
#map {
height: 100dvh;
flex: 1;
z-index: 0;
}
</style>
MapMarker.vue
<template>
<ol-feature ref="markerRef">
<ol-geom-point :coordinates="props.position"></ol-geom-point>
<ol-style>
<ol-style-icon :src="props.icon" :scale="props.scale"></ol-style-icon>
</ol-style>
</ol-feature>
</template>
<script setup>
import { defineProps, onMounted, onUnmounted } from 'vue';
import eventListener from '@/technicals/eventBus';
import { ref, computed } from 'vue';
// props
const props = defineProps({
position: {
type: Array,
default: () => [0, 0]
},
icon: {
type: String,
default: 'https://openlayers.org/en/latest/examples/data/icon.png'
},
scale: {
type: Number,
default: 1
},
actionRadius: {
type: Number,
default: NaN
},
isDraggable: {
type: Boolean,
default: true
},
markerId: {
type: String,
default: ''
}
});
// data
const markerRef = ref(null);
const marker = computed(() => markerRef.value ? markerRef.value.feature : null);
// computed
const visiblePosition = ref([NaN, NaN])
// lifecycle hooks
onMounted(() => {
console.log("Marker mounted:", props.markerId, props.position);
visiblePosition.value = props.position;
eventListener.$on('markerClicked', markerClicked);
marker.value.on('click', () => console.log("Marker clicked ?", props.markerId));
marker.value.on('pointerdrag', (event) => {
console.log("Marker move start:", props.markerId, event);
});
})
onUnmounted(() => {
eventListener.$off('markerClicked');
})
// methods
function markerClicked(event) {
// console.log("Marker,", marker.value)
// console.log("Marker Ref:", markerRef.value);
// console.log("Marker clicked event:", event);
// console.log("Marker clicked:", props.markerId)
}
</script>