// dom refs const video=document.getElementById("video") const play=document.getElementById("play") const mute=document.getElementById("mute") const seek=document.getElementById("seek") const volume=document.getElementById("volume") const controls=document.getElementById("controls") const player=document.getElementById("player") const tapUnmute=document.getElementById("tapUnmute") const rotate=document.getElementById("rotate") // player state let hideTimer,resizeTimer,lastSeek=-1 let controlsVisible=false let autoplayStartedMuted=true let rotated=false // device check const isMobile=matchMedia("(pointer:coarse)").matches||window.innerWidth<=768 controls.classList.add(isMobile?"mobile-mode":"desktop-mode") // ui sync const syncPlayState=()=>play.textContent=video.paused?"x":"▶" const syncRotateState=()=>rotate.textContent=rotated?"⟲":"⟳" function syncMuteState(){ mute.textContent=video.muted||video.volume===0?"u":"a" volume.value=video.muted?0:video.volume } // controls function showControls(){ if(!controlsVisible){ controls.classList.add("visible") controlsVisible=true } clearTimeout(hideTimer) hideTimer=setTimeout(()=>{ controls.classList.remove("visible") controlsVisible=false },isMobile?2200:1700) } // prompt const showUnmutePrompt=show=>tapUnmute.classList.toggle("visible",!!show) // layout function applyVideoLayout(){ if(rotated){ video.style.objectFit="contain" video.style.transform="translateZ(0) rotate(90deg) scale(1.15)" return } const landscape=video.videoWidth&&video.videoHeight?video.videoWidth>video.videoHeight:true const portraitScreen=window.innerHeight>window.innerWidth video.style.objectFit=isMobile&&landscape&&portraitScreen?"contain":"cover" video.style.transform="translateZ(0) scale(1.01)" } // rotate function toggleRotate(){ rotated=!rotated syncRotateState() applyVideoLayout() showControls() } // autoplay async function startPlayback(){ video.volume=1 video.muted=true try{ await video.play() }catch(e){ console.error(e) } showUnmutePrompt(true) syncPlayState() syncMuteState() syncRotateState() } // audio enable function enableSoundAndPlay(){ video.muted=false if(video.volume===0)video.volume=1 video.play().catch(()=>{}) autoplayStartedMuted=false showUnmutePrompt(false) syncMuteState() syncPlayState() } // video events video.addEventListener("play",()=>{syncPlayState();showControls()}) video.addEventListener("pause",()=>{syncPlayState();showControls()}) video.addEventListener("ended",()=>{syncPlayState();showControls()}) video.addEventListener("loadedmetadata",()=>{ applyVideoLayout() requestIdleCallback?.(()=>{ const t=document.querySelector(".video-text") if(t)t.textContent="" }) syncMuteState() syncPlayState() }) video.addEventListener("timeupdate",()=>{ if(!video.duration)return const value=((video.currentTime/video.duration)*100)|0 if(value===lastSeek)return lastSeek=value seek.value=value }) // controls play.addEventListener("click",async e=>{ e.stopPropagation() if(video.paused){ try{await video.play()}catch{} }else{ video.pause() } }) mute.addEventListener("click",e=>{ e.stopPropagation() if(video.muted||video.volume===0){ video.muted=false if(video.volume===0)video.volume=.5 autoplayStartedMuted=false showUnmutePrompt(false) }else{ video.muted=true } syncMuteState() }) seek.addEventListener("input",e=>{ e.stopPropagation() if(video.duration)video.currentTime=(e.target.value/100)*video.duration }) volume.addEventListener("input",e=>{ e.stopPropagation() video.volume=parseFloat(e.target.value) video.muted=video.volume===0 if(video.volume>0){ autoplayStartedMuted=false showUnmutePrompt(false) } syncMuteState() }) rotate.addEventListener("click",e=>{ e.stopPropagation() toggleRotate() }) tapUnmute.addEventListener("click",e=>{ e.stopPropagation() enableSoundAndPlay() }) controls.addEventListener("click",e=>e.stopPropagation()) player.addEventListener("click",()=>{ showControls() if(autoplayStartedMuted&&video.muted)enableSoundAndPlay() },{passive:true}) player.addEventListener("mousemove",showControls) player.addEventListener("mouseenter",showControls) player.addEventListener("touchstart",showControls,{passive:true}) // resize window.addEventListener("resize",()=>{ clearTimeout(resizeTimer) resizeTimer=setTimeout(applyVideoLayout,100) }) window.addEventListener("orientationchange",applyVideoLayout) // init syncPlayState() syncMuteState() syncRotateState() startPlayback()