Forgot to add MapContextMenu file
This commit is contained in:
parent
4d2a0d7180
commit
e4f0864805
160
src/components/map/MapContextMenu.vue
Normal file
160
src/components/map/MapContextMenu.vue
Normal file
@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<nav id="map__context-menu" v-show="menuVisible" ref="menuElement" :style="style">
|
||||
<ul class="menu">
|
||||
<li>
|
||||
<button ref="locationButton" type="button" v-clipboard="locationCopy">{{locationLabel}}</button>
|
||||
</li>
|
||||
<li><button type="button" v-clipboard="url">Copy link to here</button></li>
|
||||
<li><button type="button" @click.prevent="pan">Center here</button></li>
|
||||
<WorldListItem v-if="currentWorld" :world="currentWorld"></WorldListItem>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import DynmapMap from "@/leaflet/DynmapMap";
|
||||
import {computed, defineComponent, onMounted, onUnmounted} from "@vue/runtime-core";
|
||||
import {LeafletMouseEvent} from "leaflet";
|
||||
import {useStore} from "@/store";
|
||||
import WorldListItem from "@/components/sidebar/WorldListItem.vue";
|
||||
import {ref, watch} from "vue";
|
||||
import {getUrlForLocation} from "@/util";
|
||||
|
||||
export default defineComponent({
|
||||
name: "MapContextMenu",
|
||||
components: {WorldListItem},
|
||||
props: {
|
||||
leaflet: {
|
||||
type: Object as () => DynmapMap,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
const store = useStore(),
|
||||
event = ref<LeafletMouseEvent|null>(null),
|
||||
|
||||
menuElement = ref<HTMLInputElement | null>(null),
|
||||
locationButton = ref<HTMLInputElement | null>(null),
|
||||
menuVisible = computed(() => !!event.value),
|
||||
|
||||
currentProjection = computed(() => store.state.currentProjection),
|
||||
currentWorld = computed(() => store.state.currentWorld),
|
||||
currentMap = computed(() => store.state.currentMap),
|
||||
currentZoom = computed(() => store.state.currentZoom),
|
||||
|
||||
location = computed(() => {
|
||||
if(!event.value) {
|
||||
return {x: 0, y: 0, z: 0}
|
||||
}
|
||||
|
||||
return currentProjection.value.latLngToLocation(event.value.latlng, 64);
|
||||
}),
|
||||
|
||||
//Label for location button
|
||||
locationLabel = computed(() => {
|
||||
return `X: ${Math.round(location.value.x)}, Z: ${Math.round(location.value.z)}`;
|
||||
}),
|
||||
|
||||
//Location text to copy
|
||||
locationCopy = computed(() => {
|
||||
return `${Math.round(location.value.x)}, ${Math.round(location.value.z)}`;
|
||||
}),
|
||||
|
||||
//Url to copy
|
||||
url = computed(() => {
|
||||
if(!currentWorld.value || !currentMap.value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
url.hash = getUrlForLocation(currentWorld.value, currentMap.value, location.value, currentZoom.value);
|
||||
|
||||
return url;
|
||||
}),
|
||||
|
||||
style = computed(() => {
|
||||
if(!menuElement.value || !event.value) {
|
||||
return {};
|
||||
}
|
||||
|
||||
//Don't position offscreen
|
||||
const x = Math.min(
|
||||
window.innerWidth - menuElement.value.offsetWidth - 10,
|
||||
event.value.originalEvent.clientX
|
||||
),
|
||||
y = Math.min(
|
||||
window.innerHeight - menuElement.value.offsetHeight - 10,
|
||||
event.value.originalEvent.clientY
|
||||
);
|
||||
|
||||
return {
|
||||
'transform': `translate(${x}px, ${y}px)`
|
||||
}
|
||||
});
|
||||
|
||||
const handleEsc = (e: KeyboardEvent) => {
|
||||
console.log(e);
|
||||
if (e.key === "Escape") {
|
||||
closeContextMenu();
|
||||
}
|
||||
},
|
||||
closeContextMenu = () => {
|
||||
event.value = null;
|
||||
},
|
||||
pan = () => {
|
||||
if(event.value) {
|
||||
props.leaflet.panTo(event.value.latlng);
|
||||
}
|
||||
};
|
||||
|
||||
watch(menuVisible, visible => {
|
||||
if(visible) {
|
||||
requestAnimationFrame(() => locationButton.value && locationButton.value.focus());
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('click', closeContextMenu);
|
||||
window.addEventListener('keyup', handleEsc);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('click', closeContextMenu);
|
||||
window.removeEventListener('keyup', handleEsc);
|
||||
});
|
||||
|
||||
props.leaflet.on('contextmenu', (e: LeafletMouseEvent) => {
|
||||
e.originalEvent.preventDefault();
|
||||
event.value = e;
|
||||
});
|
||||
|
||||
return {
|
||||
menuVisible,
|
||||
menuElement,
|
||||
locationButton,
|
||||
url,
|
||||
|
||||
locationLabel,
|
||||
locationCopy,
|
||||
currentWorld,
|
||||
style,
|
||||
|
||||
pan,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#map__context-menu {
|
||||
background-color: var(--background-base);
|
||||
color: var(--text-base);
|
||||
border-radius: var(--border-radius);
|
||||
position: fixed;
|
||||
z-index: 1001;
|
||||
padding: 0.5rem;
|
||||
min-width: 15rem;
|
||||
max-width: 22.5rem;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user