Files
home/docs/.vitepress/theme/components/VideoBackground.vue
2026-05-13 16:24:00 +08:00

109 lines
2.1 KiB
Vue

<script setup lang="ts">
import { ref, watch, onMounted, computed } from 'vue'
import { useSettingsStore } from '../stores/settings'
import { getVideoUrl } from '../utils'
const settingsStore = useSettingsStore()
const videoRef = ref<HTMLVideoElement | null>(null)
const isLoading = ref(true)
const brightness = computed(() => settingsStore.theme.videoBrightness ?? 0.3)
onMounted(async () => {
await settingsStore.fetchVideoList()
})
watch(() => settingsStore.currentVideo, () => {
if (videoRef.value) {
videoRef.value.load()
isLoading.value = true
}
})
function onVideoCanPlay() {
isLoading.value = false
if (videoRef.value) {
videoRef.value.play().catch(() => {})
}
}
</script>
<template>
<div class="video-background">
<div v-if="isLoading" class="loading-overlay">
<div class="loading-spinner"></div>
</div>
<video
ref="videoRef"
class="video-element"
autoplay
muted
loop
playsinline
@canplay="onVideoCanPlay"
>
<source
v-if="settingsStore.currentVideo"
:src="getVideoUrl(settingsStore.currentVideo.name)"
type="video/mp4"
/>
</video>
<div class="video-overlay" :style="{ background: 'rgba(0, 0, 0, ' + brightness + ')' }"></div>
</div>
</template>
<style scoped>
.video-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
overflow: hidden;
}
.video-element {
width: 100%;
height: 100%;
object-fit: cover;
}
.video-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
pointer-events: none;
}
.loading-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #1a1a1a;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-top-color: #007AFF;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
</style>