refactor: replace YouTube lightbox with persistent background playback integration and vinyl animation state management

This commit is contained in:
Ümit Tunç
2026-06-01 08:43:16 +03:00
parent 9e6bcc22b6
commit f34fc0f2a0
2 changed files with 103 additions and 60 deletions
@@ -434,6 +434,10 @@
border-radius: 8px;
}
.project.item:has(.player:hover) {
z-index: 9999 !important;
}
.player:hover {
transform: scale(1.08) translateY(-5px);
z-index: 999;
@@ -490,6 +494,7 @@
background-image: radial-gradient(circle, #2c2727 10%, transparent 10%),
repeating-radial-gradient(circle, #2c2727, #1e1b1b 2px, #2c2727 4px);
z-index: 10;
transition: box-shadow var(--transition-time) var(--transition-method);
}
.player:hover .vinyl {
@@ -498,6 +503,7 @@
.player:hover .vinyl__circle {
animation-play-state: running;
box-shadow: 0 0 25px rgba(227, 30, 36, 0.65), 0 0 50px rgba(227, 30, 36, 0.35);
}
.vinyl__center {
@@ -88,18 +88,10 @@
</div>
@endif
{{-- YouTube Lightbox Modal --}}
{{-- Hidden Background YouTube Player --}}
@if($videoId)
<div id="youtube-lightbox" class="fixed inset-0 z-[9999] flex items-center justify-center bg-black/90 backdrop-blur-md opacity-0 pointer-events-none transition-all duration-300">
<div class="absolute inset-0" id="lightbox-bg"></div>
<div class="relative w-full max-w-4xl mx-4 aspect-video z-10 scale-95 opacity-0 transition-all duration-300" id="lightbox-content">
<button id="lightbox-close" class="absolute -top-12 right-0 text-white hover:text-red-500 transition-colors text-2xl flex items-center gap-1 font-semibold focus:outline-none">
<i class="uil uil-times before:content-['\eb50']"></i> {{ t('Kapat') }}
</button>
<div class="w-full h-full rounded-lg overflow-hidden shadow-2xl bg-black border border-white/10">
<iframe id="lightbox-iframe" class="w-full h-full border-0" src="" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
</div>
<div id="hidden-youtube-player-container" style="position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; overflow: hidden; left: -9999px;">
<div id="hidden-youtube-player"></div>
</div>
@endif
@@ -666,62 +658,107 @@ body.lightbox-open .player {
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
const cdBtn = document.getElementById('play-cd-btn');
// Load YouTube Iframe Player API dynamically
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var ytPlayer;
var isPlayerReady = false;
window.onYouTubeIframeAPIReady = function() {
ytPlayer = new YT.Player('hidden-youtube-player', {
height: '1',
width: '1',
videoId: "{{ $videoId }}",
playerVars: {
'autoplay': 0,
'controls': 0,
'disablekb': 1,
'fs': 0,
'modestbranding': 1,
'rel': 0,
'showinfo': 0
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
isPlayerReady = true;
// Check if auto-play was active from previous page
const autoPlayActive = localStorage.getItem('vinyl_auto_play') === 'true';
if (autoPlayActive) {
startPlayback();
}
}
function onPlayerStateChange(event) {
const playerEl = document.getElementById('detail-vinyl-player');
const lightbox = document.getElementById('youtube-lightbox');
const lightboxBg = document.getElementById('lightbox-bg');
const lightboxContent = document.getElementById('lightbox-content');
const lightboxClose = document.getElementById('lightbox-close');
const iframe = document.getElementById('lightbox-iframe');
const videoId = "{{ $videoId }}";
if (!playerEl) return;
if (cdBtn && lightbox && iframe) {
cdBtn.addEventListener('click', function(e) {
e.preventDefault();
// Set autoplay & enable javascript API
iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=1&enablejsapi=1`;
// Start vinyl spinning animation
if (playerEl) {
if (event.data === YT.PlayerState.PLAYING) {
playerEl.classList.add('player--playing');
}
// Show lightbox container with transition
lightbox.classList.remove('opacity-0', 'pointer-events-none');
document.body.classList.add('lightbox-open');
setTimeout(() => {
lightboxContent.classList.remove('scale-95', 'opacity-0');
}, 50);
});
function closeLightbox() {
lightboxContent.classList.add('scale-95', 'opacity-0');
lightbox.classList.add('opacity-0', 'pointer-events-none');
document.body.classList.remove('lightbox-open');
// Stop vinyl spinning animation
if (playerEl) {
localStorage.setItem('vinyl_auto_play', 'true');
} else if (event.data === YT.PlayerState.PAUSED || event.data === YT.PlayerState.ENDED) {
playerEl.classList.remove('player--playing');
if (event.data === YT.PlayerState.ENDED) {
localStorage.setItem('vinyl_auto_play', 'false');
}
}
}
// Clear source to halt playback after transition completes
setTimeout(() => {
iframe.src = "";
}, 300);
function startPlayback() {
if (isPlayerReady && ytPlayer && typeof ytPlayer.playVideo === 'function') {
ytPlayer.playVideo();
}
}
lightboxBg.addEventListener('click', closeLightbox);
lightboxClose.addEventListener('click', closeLightbox);
function pausePlayback() {
if (isPlayerReady && ytPlayer && typeof ytPlayer.pauseVideo === 'function') {
ytPlayer.pauseVideo();
}
}
// Listen for ESC key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && !lightbox.classList.contains('opacity-0')) {
closeLightbox();
document.addEventListener('DOMContentLoaded', function() {
const playBtn = document.getElementById('play-cd-btn');
const playerEl = document.getElementById('detail-vinyl-player');
if (playBtn) {
playBtn.addEventListener('click', function(e) {
e.preventDefault();
if (!isPlayerReady) return;
if (playerEl.classList.contains('player--playing')) {
pausePlayback();
localStorage.setItem('vinyl_auto_play', 'false');
} else {
startPlayback();
localStorage.setItem('vinyl_auto_play', 'true');
}
});
}
// Capture next/prev clicks to persist play state
const prevBtn = document.querySelector('.player__controls-item--prev');
const nextBtn = document.querySelector('.player__controls-item--next');
[prevBtn, nextBtn].forEach(btn => {
if (btn && btn.tagName === 'A') {
btn.addEventListener('click', function() {
if (playerEl && playerEl.classList.contains('player--playing')) {
localStorage.setItem('vinyl_auto_play', 'true');
} else {
localStorage.setItem('vinyl_auto_play', 'false');
}
});
}
});
});
</script>
@endpush