unified gost cards (mouse + touch)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<article role="button" @click.stop="cardClick" @keydown.enter.stop="cardClick" @keydown.space.prevent.stop="cardClick"
|
||||
<article :role="props.role" @click.stop="cardClick" @keydown.enter.stop="cardClick" draggable="true"
|
||||
@dragstart="dragStart" @dragend="dragEnd" @drag="dragMove" @keydown.space.prevent.stop="cardClick"
|
||||
@touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" class="card" :class="[
|
||||
isFaceUp ? 'face-up' : 'face-down',
|
||||
{ 'current-track': playerStore.currentTrack?.id === track.id },
|
||||
@@ -7,7 +8,7 @@
|
||||
]">
|
||||
<div class="flip-inner" ref="cardElement">
|
||||
<!-- Face-Up -->
|
||||
<main draggable="true" @dragstart="dragStart" @dragend="dragEnd"
|
||||
<main
|
||||
class="face-up backdrop-blur-sm border-2 z-10 card w-56 h-80 p-3 hover:shadow-xl hover:scale-110 transition-all rounded-2xl shadow-lg flex flex-col overflow-hidden">
|
||||
|
||||
<div v-if="isPlaylistTrack" class="flex items-center justify-center size-7 absolute top-7 left-7">
|
||||
@@ -60,7 +61,7 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Clone fantôme pour le drag tactile -->
|
||||
<!-- Clone fantôme unifié pour drag souris ET tactile -->
|
||||
<Teleport to="body">
|
||||
<div v-if="isDragging && touchClone" ref="ghostElement"
|
||||
class="ghost-card fixed pointer-events-none z-[9999] w-56 h-80" :style="{
|
||||
@@ -99,12 +100,14 @@ import { useDataStore } from '~/store/data';
|
||||
const props = withDefaults(defineProps<{
|
||||
track?: Track;
|
||||
isFaceUp?: boolean;
|
||||
role?: string;
|
||||
}>(), {
|
||||
track: () => {
|
||||
const dataStore = useDataStore();
|
||||
return dataStore.getRandomPlaylistTrack() || {} as Track;
|
||||
},
|
||||
isFaceUp: true,
|
||||
role: 'button'
|
||||
})
|
||||
|
||||
const playerStore = usePlayerStore()
|
||||
@@ -120,7 +123,7 @@ const isDragging = ref(false)
|
||||
const cardElement = ref<HTMLElement | null>(null)
|
||||
const ghostElement = ref<HTMLElement | null>(null)
|
||||
|
||||
// État pour le tactile
|
||||
// État unifié pour souris et tactile
|
||||
const touchClone = ref<{ x: number, y: number } | null>(null)
|
||||
const touchStartPos = ref<{ x: number, y: number } | null>(null)
|
||||
const longPressTimer = ref<number | null>(null)
|
||||
@@ -135,18 +138,40 @@ const cardClick = () => {
|
||||
hasMovedDuringPress.value = false
|
||||
}
|
||||
|
||||
// Drag desktop
|
||||
// Drag desktop - utilise maintenant ghostElement
|
||||
const dragStart = (event: DragEvent) => {
|
||||
if (event.dataTransfer && cardElement.value) {
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
event.dataTransfer.setData('application/json', JSON.stringify(props.track));
|
||||
|
||||
// Créer une image transparente pour masquer l'image par défaut du navigateur
|
||||
const img = new Image();
|
||||
img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
event.dataTransfer.setDragImage(img, 0, 0);
|
||||
|
||||
// Activer le clone fantôme
|
||||
isDragging.value = true
|
||||
touchClone.value = {
|
||||
x: event.clientX,
|
||||
y: event.clientY
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Nouveau: suivre le mouvement de la souris pendant le drag
|
||||
const dragMove = (event: DragEvent) => {
|
||||
if (isDragging.value && touchClone.value && event.clientX !== 0 && event.clientY !== 0) {
|
||||
touchClone.value = {
|
||||
x: event.clientX,
|
||||
y: event.clientY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
const dragEnd = (event: DragEvent) => {
|
||||
isDragging.value = false
|
||||
touchClone.value = null
|
||||
|
||||
if (event.dataTransfer?.dropEffect === 'move' && instance?.vnode?.el?.parentNode) {
|
||||
instance.vnode.el.parentNode.removeChild(instance.vnode.el);
|
||||
@@ -400,7 +425,7 @@ onUnmounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
/* Ghost card styles */
|
||||
/* Ghost card styles - maintenant unifié pour souris et tactile */
|
||||
.ghost-card {
|
||||
transition: none;
|
||||
|
||||
@@ -417,4 +442,4 @@ onUnmounted(() => {
|
||||
perspective: 1000px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
Reference in New Issue
Block a user