Started vue based map marker menu
This commit is contained in:
@@ -3,6 +3,7 @@ import type { MapMarker, PlayerMarker } from '@/types/Leaflet';
|
|||||||
|
|
||||||
import markersData from '@/components/maps/data/markers.json'
|
import markersData from '@/components/maps/data/markers.json'
|
||||||
import playersData from '@/components/maps/data/players.json'
|
import playersData from '@/components/maps/data/players.json'
|
||||||
|
import MarkerCreator from './overlay/MarkerCreator.vue';
|
||||||
|
|
||||||
const markers = markersData.data as MapMarker[]
|
const markers = markersData.data as MapMarker[]
|
||||||
const players = playersData as PlayerMarker
|
const players = playersData as PlayerMarker
|
||||||
@@ -10,6 +11,8 @@ const players = playersData as PlayerMarker
|
|||||||
|
|
||||||
<div class="world-wrapper">
|
<div class="world-wrapper">
|
||||||
<div id="world"></div>
|
<div id="world"></div>
|
||||||
|
|
||||||
|
<MarkerCreator client:load />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script lang="ts" define:vars={{ markers, players }} defer>
|
<script lang="ts" define:vars={{ markers, players }} defer>
|
||||||
@@ -358,6 +361,8 @@ body {
|
|||||||
.world-wrapper {
|
.world-wrapper {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
|
z-index: 0;
|
||||||
|
isolation: isolate;
|
||||||
|
|
||||||
#world {
|
#world {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const players = playersData as PlayerMarker
|
|||||||
---
|
---
|
||||||
|
|
||||||
<div class="world-overlay">
|
<div class="world-overlay">
|
||||||
<SearchMarkers client:load markers={markers} players={players}/>
|
<SearchMarkers client:load markers={markers} players={players} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
152
src/components/maps/overlay/MarkerCreator.vue
Normal file
152
src/components/maps/overlay/MarkerCreator.vue
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { onClickOutside, onLongPress, useCssVar, useMouse, useTimeout, useTimeoutFn } from '@vueuse/core';
|
||||||
|
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
const markerMenu = ref<HTMLMenuElement>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appearing behaviour
|
||||||
|
*/
|
||||||
|
const isActive = ref<Boolean>(false)
|
||||||
|
|
||||||
|
const hasBeenLongPressed = ref<Boolean>(false)
|
||||||
|
const longPressDelay = 500
|
||||||
|
const longPressOver = 1100
|
||||||
|
|
||||||
|
const longPressTimer = useTimeoutFn(() => {
|
||||||
|
hasBeenLongPressed.value = false
|
||||||
|
}, longPressOver)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener('contextmenu', handleContextMenu)
|
||||||
|
onLongPress(document.documentElement, handleLongPress, { delay: longPressDelay })
|
||||||
|
onClickOutside(markerMenu, handleClickOutside)
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleLongPress(e: Event) {
|
||||||
|
console.log(e)
|
||||||
|
|
||||||
|
hasBeenLongPressed.value = true
|
||||||
|
longPressTimer.start()
|
||||||
|
|
||||||
|
showMenu()
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClickOutside(e: Event) {
|
||||||
|
console.log(e)
|
||||||
|
|
||||||
|
if (!hasBeenLongPressed.value) {
|
||||||
|
hideMenu()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleContextMenu(e: Event) {
|
||||||
|
console.log(e)
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
showMenu()
|
||||||
|
updateMenuPosition()
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMenu() {
|
||||||
|
isActive.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideMenu() {
|
||||||
|
isActive.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Positioning
|
||||||
|
*/
|
||||||
|
const mouse = useMouse()
|
||||||
|
const mouseXVar = useCssVar('--mouse-x', markerMenu)
|
||||||
|
const mouseYVar = useCssVar('--mouse-y', markerMenu)
|
||||||
|
|
||||||
|
watch( isActive, (o, n) => {
|
||||||
|
// If new value is active
|
||||||
|
if (o) {
|
||||||
|
updateMenuPosition()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function updateMenuPosition() {
|
||||||
|
storeMousePosition()
|
||||||
|
updateCSSVars()
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCSSVars() {
|
||||||
|
mouseXVar.value = `${mouse.x.value.toFixed()}px`
|
||||||
|
mouseYVar.value = `${mouse.y.value.toFixed()}px`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Storing data and logic
|
||||||
|
*/
|
||||||
|
const lastHeldXPosition = ref<number>(0)
|
||||||
|
const lastHeldYPosition = ref<number>(0)
|
||||||
|
|
||||||
|
function storeMousePosition() {
|
||||||
|
lastHeldXPosition.value = mouse.x.value
|
||||||
|
lastHeldYPosition.value = mouse.y.value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Transition>
|
||||||
|
<menu v-show="isActive" ref="markerMenu">
|
||||||
|
<li>
|
||||||
|
<button>
|
||||||
|
Add a marker {{ lastHeldXPosition }} {{ lastHeldYPosition }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</menu>
|
||||||
|
</Transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
menu {
|
||||||
|
--mouse-y: 0px;
|
||||||
|
--mouse-x: 0px;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: calc(var(--mouse-y) - .5rem);
|
||||||
|
left: calc(var(--mouse-x) + .75rem);
|
||||||
|
background-color: var(--white);
|
||||||
|
border: 1px solid var(--slate-400);
|
||||||
|
border-radius: .3rem;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.3) 0px 4px 12px;
|
||||||
|
z-index: 1000;
|
||||||
|
transition-property: top, left;
|
||||||
|
transition-duration: .16s;
|
||||||
|
transition-timing-function: cubic-bezier(0.785, 0.135, 0.15, 0.86);
|
||||||
|
|
||||||
|
li {
|
||||||
|
a, button {
|
||||||
|
display: block;
|
||||||
|
padding: .5rem 1.2rem;
|
||||||
|
font-size: .8em;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus-within {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ANIMATIONS
|
||||||
|
*/
|
||||||
|
.v-enter-active,
|
||||||
|
.v-leave-active {
|
||||||
|
transition: all .16s cubic-bezier(0.445, 0.05, 0.55, 0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-enter-from,
|
||||||
|
.v-leave-to {
|
||||||
|
transform: translateY(.5rem);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user