背景视频同步播放

This commit is contained in:
LL
2025-11-19 15:11:50 +08:00
parent 0c5ecababa
commit f72f73680e
3 changed files with 49 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ document.addEventListener('DOMContentLoaded', () => {
// ===== 视频逻辑 ===== // ===== 视频逻辑 =====
const player = document.getElementById('player'); const player = document.getElementById('player');
const bgVideo = document.getElementById('bgVideo');
const videoWrap = document.getElementById('videoWrap'); const videoWrap = document.getElementById('videoWrap');
const videoPanel = document.getElementById('video'); const videoPanel = document.getElementById('video');
const includeLocalToggle = document.getElementById('includeLocalToggle'); const includeLocalToggle = document.getElementById('includeLocalToggle');
@@ -68,7 +69,18 @@ document.addEventListener('DOMContentLoaded', () => {
if (!playlist.length) return; if (!playlist.length) return;
index = (i + playlist.length) % playlist.length; index = (i + playlist.length) % playlist.length;
const item = playlist[index]; const item = playlist[index];
try { player.crossOrigin = 'anonymous'; } catch {}
player.src = item.url; player.src = item.url;
if (bgVideo) {
try {
bgVideo.muted = true;
bgVideo.loop = true;
bgVideo.setAttribute('playsinline', '');
bgVideo.src = item.url;
bgVideo.load();
bgVideo.play().catch(() => {});
} catch {}
}
// 已移除标题展示,无需设置文本 // 已移除标题展示,无需设置文本
player.load(); player.load();
if (videoPanel) videoPanel.style.setProperty('--progress', '0'); if (videoPanel) videoPanel.style.setProperty('--progress', '0');
@@ -186,16 +198,42 @@ document.addEventListener('DOMContentLoaded', () => {
if (!isFinite(d) || d <= 0) return; if (!isFinite(d) || d <= 0) return;
const p = Math.max(0, Math.min(1, t / d)); const p = Math.max(0, Math.min(1, t / d));
if (videoPanel) videoPanel.style.setProperty('--progress', String(p * 360)); if (videoPanel) videoPanel.style.setProperty('--progress', String(p * 360));
if (!bgCtx) return;
const now = Date.now();
if (now - bgLastUpdate < 1500) return;
bgLastUpdate = now;
try {
bgCtx.drawImage(player, 0, 0, bgCanvas.width, bgCanvas.height);
const img = bgCtx.getImageData(0, 0, bgCanvas.width, bgCanvas.height).data;
let r = 0, g = 0, b = 0, cnt = 0;
for (let i = 0; i < img.length; i += 4) {
r += img[i]; g += img[i+1]; b += img[i+2]; cnt++;
}
if (cnt > 0) {
r = Math.round(r / cnt); g = Math.round(g / cnt); b = Math.round(b / cnt);
const mix = (c) => Math.round(c * 0.25 + 255 * 0.75);
const base = `rgb(${mix(r)},${mix(g)},${mix(b)})`;
const accent = `rgba(${r},${g},${b},0.2)`;
document.documentElement.style.setProperty('--bg-base', base);
document.documentElement.style.setProperty('--bg-accent', accent);
}
} catch {}
}); });
// 播放结束自动下一条 // 播放结束自动下一条
player.addEventListener('ended', () => { next(); }); player.addEventListener('ended', () => { next(); });
const bgCanvas = document.createElement('canvas');
bgCanvas.width = 32; bgCanvas.height = 18;
const bgCtx = bgCanvas.getContext('2d', { willReadFrequently: true });
let bgLastUpdate = 0;
player.addEventListener('loadeddata', () => { bgLastUpdate = 0; });
let lastLoggedVideo = ''; let lastLoggedVideo = '';
player.addEventListener('play', () => { player.addEventListener('play', () => {
const cur = player.currentSrc || player.src || ''; const cur = player.currentSrc || player.src || '';
if (!cur || cur === lastLoggedVideo) return; if (!cur || cur === lastLoggedVideo) return;
lastLoggedVideo = cur; lastLoggedVideo = cur;
if (bgVideo) { try { bgVideo.play().catch(() => {}); } catch {} }
track({ event: 'video_play', page: location.pathname, url: cur, title: '' }); track({ event: 'video_play', page: location.pathname, url: cur, title: '' });
}); });

View File

@@ -7,6 +7,8 @@
--radius: 6px; --radius: 6px;
--shadow: 0 6px 14px rgba(226, 38, 38, 0.08); --shadow: 0 6px 14px rgba(226, 38, 38, 0.08);
--shadow-hover: 0 8px 20px rgba(226, 38, 38, 0.12); --shadow-hover: 0 8px 20px rgba(226, 38, 38, 0.12);
--bg-base: #ffffff;
--bg-accent: #fff5f5;
} }
* { box-sizing: border-box; } * { box-sizing: border-box; }
@@ -17,10 +19,14 @@ body {
sans-serif; sans-serif;
color: #333; color: #333;
background: background:
radial-gradient(1200px 400px at 10% -20%, #fff5f5 0%, transparent 40%), radial-gradient(1200px 400px at 10% -20%, var(--bg-accent) 0%, transparent 40%),
linear-gradient(#ffffff, #ffffff); linear-gradient(var(--bg-base), var(--bg-base));
} }
#bgVideoContainer { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
#bgVideoContainer video { width: 100%; height: 100%; object-fit: cover; filter: blur(36px) saturate(120%) brightness(1.05) contrast(1.05); transform: scale(1.06); opacity: 0.5; }
.page { position: relative; z-index: 1; }
.page { .page {
max-width: var(--page-max); max-width: var(--page-max);
padding: 16px; padding: 16px;
@@ -33,7 +39,7 @@ body {
top: 0; top: 0;
z-index: 100; z-index: 100;
border: var(--border); border: var(--border);
background: #fff; background: rgba(255,255,255,0.95);
min-height: 60px; min-height: 60px;
padding: 10px 16px; padding: 10px 16px;
display: flex; display: flex;
@@ -69,7 +75,7 @@ body {
padding: 8px 14px; padding: 8px 14px;
border-radius: 999px; border-radius: 999px;
border: 1px solid var(--red); border: 1px solid var(--red);
background: #fff; background: rgba(255,255,255,0.92);
transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease; transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
} }

View File

@@ -153,6 +153,7 @@
</style> </style>
</head> </head>
<body> <body>
<div id="bgVideoContainer" aria-hidden="true"><video id="bgVideo" muted autoplay loop playsinline></video></div>
<div class="page"> <div class="page">
<header class="menu"> <header class="menu">
<div class="menu__logo">菜单</div> <div class="menu__logo">菜单</div>