add cards & tracks
This commit is contained in:
		| @@ -130,7 +130,7 @@ onMounted(() => { | ||||
|   const down = (ev: PointerEvent) => { | ||||
|     ev.preventDefault() | ||||
|     dragging = true | ||||
|     scene.value?.setPointerCapture(ev.pointerId) | ||||
|     box.value?.setPointerCapture(ev.pointerId) | ||||
|     lastPointer = { x: ev.clientX, y: ev.clientY, time: performance.now() } | ||||
|     velocity = { x: 0, y: 0 } | ||||
|     if (raf) { cancelAnimationFrame(raf); raf = null } | ||||
| @@ -158,17 +158,17 @@ onMounted(() => { | ||||
|   const end = (ev: PointerEvent) => { | ||||
|     if (!dragging) return | ||||
|     dragging = false | ||||
|     try { scene.value?.releasePointerCapture(ev.pointerId) } catch { } | ||||
|     try { box.value?.releasePointerCapture(ev.pointerId) } catch { } | ||||
|     if (enableInertia && (Math.abs(velocity.x) > minVelocity || Math.abs(velocity.y) > minVelocity)) { | ||||
|       if (!raf) raf = requestAnimationFrame(tickInertia) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   scene.value?.addEventListener('pointerdown', down) | ||||
|   scene.value?.addEventListener('pointermove', move) | ||||
|   scene.value?.addEventListener('pointerup', end) | ||||
|   scene.value?.addEventListener('pointercancel', end) | ||||
|   scene.value?.addEventListener('pointerleave', end) | ||||
|   box.value?.addEventListener('pointerdown', down) | ||||
|   box.value?.addEventListener('pointermove', move) | ||||
|   box.value?.addEventListener('pointerup', end) | ||||
|   box.value?.addEventListener('pointercancel', end) | ||||
|   box.value?.addEventListener('pointerleave', end) | ||||
|  | ||||
|   onBeforeUnmount(() => { | ||||
|     cancelAnimationFrame(raf!) | ||||
|   | ||||
| @@ -1,14 +1,17 @@ | ||||
| <template> | ||||
|   <article class="relative"> | ||||
|     <main | ||||
|       class="absolute top-0 backdrop-blur-sm z-40 -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-10 bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> | ||||
|       class="backdrop-blur-sm border-2 -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-40 hover:bg-opacity-80 hover:shadow-xl transition-all bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> | ||||
|       <!-- Cover --> | ||||
|       <figure class="flex-1 overflow-hidden rounded-t-xl"> | ||||
|       <figure @click="playerStore.playTrack(props.track)" class="flex-1 overflow-hidden rounded-t-xl cursor-pointer"> | ||||
|         <img :src="coverUrl" alt="Pochette de l'album" class="w-full h-full object-cover object-center" /> | ||||
|       </figure> | ||||
|  | ||||
|       <!-- Body --> | ||||
|       <div class="p-3 text-center bg-white rounded-b-xl"> | ||||
|         <div class="label"> | ||||
|           {{ props.track.order }} | ||||
|         </div> | ||||
|         <h2 class="text-base text-neutral-800 font-bold truncate">{{ props.track.title }}</h2> | ||||
|         <p class="text-sm text-neutral-500 truncate"> | ||||
|           {{ props.track.artist.name }} | ||||
| @@ -17,11 +20,14 @@ | ||||
|     </main> | ||||
|  | ||||
|     <footer | ||||
|       class="absolute top-0 ml-32 backdrop-blur-sm -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-10 bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> | ||||
|       class="ml-32 backdrop-blur-sm -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-10 bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> | ||||
|       <!-- Back --> | ||||
|       <div class="h-full flex p-16 text-center bg-slate-800 rounded-xl"> | ||||
|         <img src="/favicon.svg" /> | ||||
|       </div> | ||||
|       <div class="label"> | ||||
|         {{ props.track.id }} | ||||
|       </div> | ||||
|     </footer> | ||||
|   </article> | ||||
|  | ||||
| @@ -29,7 +35,19 @@ | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import type { Track } from '~~/types/types' | ||||
| import { usePlayerStore } from '~/store/player' | ||||
|  | ||||
| const props = defineProps<{ track: Track }>() | ||||
| const coverUrl = `https://f4.bcbits.com/img/${props.track.artist.coverId}_4.jpg` | ||||
| </script> | ||||
| const playerStore = usePlayerStore() | ||||
| const coverUrl = props.track.coverId.startsWith('http') | ||||
|   ? props.track.coverId | ||||
|   : `https://f4.bcbits.com/img/${props.track.coverId}_4.jpg`; | ||||
| </script> | ||||
|  | ||||
| <style> | ||||
| .label { | ||||
|   @apply rounded-full size-7 p-2 bg-esyellow leading-3 -mt-6; | ||||
|   font-weight: bold; | ||||
|   text-align: center; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										38
									
								
								app/components/molecule/player.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/components/molecule/player.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| <template> | ||||
|   <audio ref="audioRef" class="fixed z-50 bottom-0 left-1/2 -translate-x-1/2 w-1/2" | ||||
|     :src="playerStore.currentTrack ? playerStore.getCompilationUrlFromTrack(playerStore.currentTrack) : ''" controls | ||||
|     @timeupdate="updatePosition" @ended="onEnded" /> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { ref, onMounted, watch } from 'vue' | ||||
| import { usePlayerStore } from '~/store/player' | ||||
|  | ||||
| const playerStore = usePlayerStore() | ||||
| const audioRef = ref<HTMLAudioElement | null>(null) | ||||
|  | ||||
| onMounted(() => { | ||||
|   if (audioRef.value) playerStore.audio = audioRef.value | ||||
| }) | ||||
|  | ||||
| // Mettre à jour la position | ||||
| function updatePosition() { | ||||
|   if (audioRef.value) playerStore.position = audioRef.value.currentTime | ||||
| } | ||||
|  | ||||
| function onEnded() { | ||||
|   playerStore.isPlaying = false | ||||
| } | ||||
|  | ||||
| // Si la track change, mettre à jour le src et le start | ||||
| watch( | ||||
|   () => playerStore.currentTrack, | ||||
|   (newTrack) => { | ||||
|     if (newTrack && audioRef.value) { | ||||
|       audioRef.value.src = newTrack.url | ||||
|       audioRef.value.currentTime = newTrack.start || 0 | ||||
|       if (playerStore.isPlaying) audioRef.value.play() | ||||
|     } | ||||
|   } | ||||
| ) | ||||
| </script> | ||||
		Reference in New Issue
	
	Block a user