-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1129 from geoadmin/pb-199-add-new-point
PB-199: add new point on an existing line
- Loading branch information
Showing
11 changed files
with
382 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
<script setup> | ||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' | ||
import { onMounted, ref } from 'vue' | ||
import { useI18n } from 'vue-i18n' | ||
import { useStore } from 'vuex' | ||
import { EditMode } from '@/store/modules/drawing.store' | ||
import { useTippyTooltip } from '@/utils/composables/useTippyTooltip' | ||
const dispatcher = { dispatcher: 'AddVertexButton.vue' } | ||
const props = defineProps({ | ||
tooltipText: { | ||
type: String, | ||
default: 'modify_add_vertex', | ||
}, | ||
// If true, the button will add a vertex in the reverse direction | ||
reverse: { | ||
type: Boolean, | ||
default: false, | ||
}, | ||
}) | ||
const emit = defineEmits(['button-mounted']) | ||
const buttonRef = ref(null) | ||
const i18n = useI18n() | ||
const store = useStore() | ||
useTippyTooltip('#addVertexButton [data-tippy-content]', { placement: 'left' }) | ||
onMounted(() => { | ||
// Emit an event to notify the parent component that the button is mounted | ||
emit('button-mounted', buttonRef.value) | ||
}) | ||
function addVertex() { | ||
store.dispatch('setEditingMode', { | ||
mode: EditMode.EXTEND, | ||
reverseLineStringExtension: props.reverse, | ||
...dispatcher, | ||
}) | ||
} | ||
</script> | ||
|
||
<template> | ||
<div id="addVertexButton" ref="buttonRef"> | ||
<button | ||
class="overlay-button d-print-none" | ||
:data-tippy-content="i18n.t(props.tooltipText)" | ||
@click="addVertex" | ||
> | ||
<font-awesome-icon :icon="['fas', 'plus']" /> | ||
</button> | ||
</div> | ||
</template> | ||
|
||
<style lang="scss" scoped> | ||
@import '@/modules/map/scss/toolbox-buttons'; | ||
</style> |
125 changes: 125 additions & 0 deletions
125
src/modules/drawing/components/AddVertexButtonOverlay.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
<script setup> | ||
import { LineString } from 'ol/geom' | ||
import Overlay from 'ol/Overlay' | ||
import { computed, onMounted, ref, watch } from 'vue' | ||
import { inject } from 'vue' | ||
import { onUnmounted } from 'vue' | ||
import { useStore } from 'vuex' | ||
import AddVertexButton from '@/modules/drawing/components/AddVertexButton.vue' | ||
const props = defineProps({ | ||
lineString: { | ||
type: LineString, | ||
required: true, | ||
}, | ||
}) | ||
const coordinates = computed(() => props.lineString.coordinates) | ||
const olMap = inject('olMap') | ||
const firstButtonOverlay = ref(null) | ||
const lastButtonOverlay = ref(null) | ||
const firstButtonCoordinate = ref(null) | ||
const lastButtonCoordinate = ref(null) | ||
const store = useStore() | ||
const selectedEditableFeatures = computed(() => store.state.features.selectedEditableFeatures) | ||
const selectedFeatureType = computed(() => { | ||
if (selectedEditableFeatures.value && selectedEditableFeatures.value.length > 0) { | ||
const selectedFeature = selectedEditableFeatures.value[0] | ||
return selectedFeature.featureType | ||
} | ||
return null | ||
}) | ||
const calculateOffset = (point1, point2, distance) => { | ||
if (!point1 || !point2) { | ||
return [distance, -distance] | ||
} | ||
// Vector from point1 to point2 | ||
const dx = point2[0] - point1[0] | ||
const dy = point2[1] - point1[1] | ||
// Normalize the vector | ||
const length = Math.sqrt(dx * dx + dy * dy) | ||
if (length === 0) return [distance, -distance] | ||
// Get unit vector in opposite direction | ||
const ux = -dx / length | ||
const uy = -dy / length | ||
// There is minus in y-direction because the y-axis is inverted in the map | ||
return [ux * distance, -uy * distance] | ||
} | ||
const updateButtonPositions = () => { | ||
const coords = coordinates.value | ||
firstButtonCoordinate.value = coords[0] | ||
lastButtonCoordinate.value = coords[coords.length - 1] | ||
let distance = 35 | ||
const firstOffset = calculateOffset(coords[0], coords[1], distance) | ||
// adding this so that the button is not on top of the measure line label | ||
if (selectedFeatureType.value === 'MEASURE') { | ||
distance = distance + 40 | ||
} | ||
const lastOffset = calculateOffset( | ||
coords[coords.length - 1], | ||
coords[coords.length - 2], | ||
distance | ||
) | ||
if (firstButtonOverlay.value) { | ||
firstButtonOverlay.value.setPosition(firstButtonCoordinate.value) | ||
firstButtonOverlay.value.setOffset(firstOffset) | ||
} | ||
if (lastButtonOverlay.value) { | ||
lastButtonOverlay.value.setPosition(lastButtonCoordinate.value) | ||
lastButtonOverlay.value.setOffset(lastOffset) | ||
} | ||
} | ||
const onFirstButtonMounted = (buttonElement) => { | ||
firstButtonOverlay.value = new Overlay({ | ||
element: buttonElement, | ||
positioning: 'center-center', | ||
stopEvent: true, | ||
}) | ||
olMap.addOverlay(firstButtonOverlay.value) | ||
updateButtonPositions() | ||
} | ||
const onLastButtonMounted = (buttonElement) => { | ||
lastButtonOverlay.value = new Overlay({ | ||
element: buttonElement, | ||
positioning: 'center-center', | ||
stopEvent: true, | ||
}) | ||
olMap.addOverlay(lastButtonOverlay.value) | ||
updateButtonPositions() | ||
} | ||
watch(coordinates, updateButtonPositions) | ||
onMounted(() => { | ||
updateButtonPositions() | ||
}) | ||
onUnmounted(() => { | ||
if (firstButtonOverlay.value) { | ||
olMap.removeOverlay(firstButtonOverlay.value) | ||
} | ||
if (lastButtonOverlay.value) { | ||
olMap.removeOverlay(lastButtonOverlay.value) | ||
} | ||
}) | ||
</script> | ||
|
||
<template> | ||
<AddVertexButton :reverse="true" @button-mounted="onFirstButtonMounted" /> | ||
<AddVertexButton :reverse="false" @button-mounted="onLastButtonMounted" /> | ||
</template> |
Oops, something went wrong.