Started vue based map marker menu

This commit is contained in:
Alexis
2024-01-05 21:38:28 +01:00
parent c9da4fe4d1
commit ac3aef4366
4 changed files with 159 additions and 2 deletions

View File

@@ -3,6 +3,7 @@ import type { MapMarker, PlayerMarker } from '@/types/Leaflet';
import markersData from '@/components/maps/data/markers.json'
import playersData from '@/components/maps/data/players.json'
import MarkerCreator from './overlay/MarkerCreator.vue';
const markers = markersData.data as MapMarker[]
const players = playersData as PlayerMarker
@@ -10,6 +11,8 @@ const players = playersData as PlayerMarker
<div class="world-wrapper">
<div id="world"></div>
<MarkerCreator client:load />
</div>
<script lang="ts" define:vars={{ markers, players }} defer>
@@ -358,6 +361,8 @@ body {
.world-wrapper {
position: fixed;
inset: 0;
z-index: 0;
isolation: isolate;
#world {
height: 100%;

View File

@@ -11,7 +11,7 @@ const players = playersData as PlayerMarker
---
<div class="world-overlay">
<SearchMarkers client:load markers={markers} players={players}/>
<SearchMarkers client:load markers={markers} players={players} />
</div>
<script>

View 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>

View File

@@ -7,4 +7,4 @@ import WorldMapOverlay from '../components/maps/WorldMapOverlay.astro'
<Layout title="Cartographie">
<WorldMapOverlay />
<WorldMap />
</Layout>
</Layout>