杨帆 发表于 2026-6-13 13:45

红影 发表于 2026-6-13 13:04
这个代码真的很不错

欢迎影子欣赏~能看到视频吗?

杨帆 发表于 2026-6-13 13:48

也曾年轻 发表于 2026-6-13 10:44
是这个视频没显示, 它采用的是http协议

是,看来用<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">也没效果

也曾年轻 发表于 2026-6-13 13:49

本帖最后由 也曾年轻 于 2026-6-14 07:25 编辑 <br /><br />杨帆 发表于 2026-6-13 13:48
是,看来用也没效果

<!--
<html>
<head>
<meta charset="utf-8">
<meta name="referrer" content="never" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
<title>美丽中国</title>
<style>
@import url("https://fonts.googleapis.com/css2?family=Liu+Jian+Mao+Cao&family=Long+Cang&family=Ma+Shan+Zheng&family=ZCOOL+KuaiLe&family=ZCOOL+QingKe+HuangYou&display=swap");
.showcase {position: relative; display: grid; place-items: center; margin: 30px 0; width: 1280px; height: 750px; left: calc(50% - 81px); transform: translateX(-50%); box-shadow: 3px 3px 6px gray; overflow: hidden; z-index: 1; background: #000 url('shturl.cc/Xl44XwvECfb2xPoI0GdxSCpwpGKkBJg5Myo') no-repeat center/cover; font-family: "ZCOOL KuaiLe","Ma Shan Zheng","Long Cang","华文行楷","SimHei","Arial","sans-serif";}
.bg-canvas {position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; pointer-events: none;}
#spectrumCanvas {position: absolute; bottom: 0; left: 0; width: 100%; height: 100%; z-index: 2; display: block; background: transparent; pointer-events: none;}
#lyricCanvas {position: absolute; top: 300px; left: 50%; transform: translateX(-50%); width: 800px; height: 140px; z-index: 15; background: transparent; pointer-events: auto;}
#player {position: absolute; z-index: 6; right: 28px; top: 20px; width: 200px; height: 200px; cursor: pointer; transition: transform 0.3s ease, background 0.3s ease; display: flex; align-items: center; justify-content: center;}
@keyframes float {0%{transform: translateY(0);} 100%{transform: translateY(-20px);}}
#player.playing {animation: float 3s ease-in-out infinite alternate;}
.time-display {position: absolute; top: 180px; left: calc(50%); transform: translateX(-50%); padding: 6px 18px; font-size: 18px; font-weight: bold; color: #e6f7ff; letter-spacing: 1px; z-index: 16; pointer-events: none; font-family: monospace; white-space: nowrap; text-shadow: 1px 1px 0 #003366, -1px -1px 0 #003366, 1px -1px 0 #003366, -1px 1px 0 #003366;}
.song-title {position: absolute; top: 70px; left: calc(50% - 200px); transform: translateX(-50%); width: 30%; height: 10%; color: #ff3333; font-family: 'Microsoft YaHei', "华文新魏", cursive; font-size: 5rem; margin-bottom: 20px; letter-spacing: 6px; z-index: 2; transform: perspective(800px) rotateY(-20deg); text-shadow: 1px 1px 0 #ffffff, 2px 2px 0 #ffffff, 3px 3px 0 #ffffff; background: none; border: none; box-shadow: none; padding: 0; }
.dancer {position: relative; mix-blend-mode: screen; z-index: 6; }
.vid1 {position: absolute; z-index: 1; left: 0%; top: 0%; width: 100%; height: 100%; object-fit: cover; pointer-events: none; object-position: center; will-change: transform;}
.vid2 {position: absolute; z-index: 1; left: 0%; top: 0%; width: 100%; height: 100%; object-fit: cover; pointer-events: none; object-position: center; mix-blend-mode: screen; will-change: transform; opacity: .1;}
#fullscreen {border-radius: 4px; position: absolute; color: DarkGray; padding: 4px 8px; z-index: 12; font-size: 25px; border: none; cursor: pointer; top: 25px; left: 25px; background: transparent;}
#fullscreen:hover {font-style: italic;}
</style>
    <div class="showcase" id="showcase">
    <div id="fullscreen">全屏欣赏</div>
    <div class="song-title">美丽中国</div>
    <canvas id="bgCanvas" class="bg-canvas"></canvas>
    <canvas id="spectrumCanvas"></canvas>
    <canvas id="lyricCanvas" width="800" height="160" style="width:800px; height:160px;"></canvas>
    <video class="vid1" src="https://i.uik.cc/view.php/350c657ead14f6d252e3ba9d90ff0a4e.mp4" preload="auto" autoplay loop playsinline muted></video>
    <video class="vid2" src="https://wj.zp68.com/lxx/yunhua/2025/09/30/24.mp4" preload="auto" autoplay loop playsinline muted></video>
    <img class="dancer" id="player" data-gif="https://pic1.imgdb.cn/item/6a2b701e240596c6e205bda9.gif" data-png="https://pic1.imgdb.cn/item/6a2b7067240596c6e205be33.png" src="https://pic1.imgdb.cn/item/6a2b701e240596c6e205bda9.gif" title = "播放/暂停">
    <div class="time-display" id="timeDisplay">0:00 / 0:00</div>
</div>
<script>
(function() {
    const CANVAS_W = 1280;
    const CANVAS_H = 750;
    const AUDIO_LOCAL = '';
    const AUDIO_FALLBACK = 'https://music.163.com/song/media/outer/url?id=28465276.mp3';
    const FILL_VIDEO_URL = 'https://img2.tukuppt.com/video_show/2421007/00/01/57/5b46335976efe.mp4';
    const FILL_VIDEO_FALLBACK = 'https://img2.tukuppt.com/video_show/2421007/00/01/57/5b46335976efe.mp4';
    const TOTAL_FRAMES = 24;
    const FRAME_DURATION = 0.1;
    const FRAME_BASE_PATH = 'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/4ac300b8cc4fe31f96e6d2d0109832f3_preview.webp';
    const FRAME_EXT = 'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/4ac300b8cc4fe31f96e6d2d0109832f3_preview.webp';
    const vids = document.querySelectorAll('video');
    const fullscreen = document.getElementById('fullscreen');
    const papa = document.getElementById('showcase');
    function getFrameUrl(frameNumber) {
      const padded = frameNumber.toString().padStart(2, '0');
      return `${FRAME_BASE_PATH}frame_${padded}_delay-0.1s${FRAME_EXT}`;
    }
    let bgFrames = [];
    let bgFramesLoaded = false;
    let bgCanvas = document.getElementById('bgCanvas');
    let bgCtx = bgCanvas.getContext('2d');
    let bgAnimationId = null;
    function loadBackgroundFrames() {
      let loadedCount = 0;
      let failedCount = 0;
      for (let idx = 0; idx < TOTAL_FRAMES; idx++) {
            const img = new Image();
            img.onload = () => {
                loadedCount++;
                if (loadedCount + failedCount === TOTAL_FRAMES) {
                  bgFramesLoaded = true;
                  drawBackgroundFrame(0);
                  if (isPlaying && !bgAnimationId) {
                        startBackgroundAnimation();
                  }
                }
            };
            img.onerror = () => {
                failedCount++;
                bgFrames = null;
                if (loadedCount + failedCount === TOTAL_FRAMES) {
                  bgFramesLoaded = true;
                  drawBackgroundFrame(0);
                  if (isPlaying && !bgAnimationId) {
                        startBackgroundAnimation();
                  }
                }
            };
            img.src = getFrameUrl(idx);
            bgFrames.push(img);
      }
    }
    function drawBackgroundFrame(frameIndex) {
      if (!bgFramesLoaded) return;
      const w = bgCanvas.clientWidth;
      const h = bgCanvas.clientHeight;
      if (bgCanvas.width !== w || bgCanvas.height !== h) {
            bgCanvas.width = w;
            bgCanvas.height = h;
      }
      let img = bgFrames;
      let actualIndex = frameIndex;
      while (actualIndex >= 0 && (!img || !img.complete || img.naturalWidth === 0)) {
            actualIndex--;
            img = actualIndex >= 0 ? bgFrames : null;
      }
      if (!img || !img.complete) return;
      const imgW = img.naturalWidth;
      const imgH = img.naturalHeight;
      const scale = Math.max(w / imgW, h / imgH);
      const drawW = imgW * scale;
      const drawH = imgH * scale;
      const dx = (w - drawW) / 2;
      const dy = (h - drawH) / 2;
      bgCtx.drawImage(img, dx, dy, drawW, drawH);
    }
    function getFrameIndexFromTime(currentTime) {
      const totalCycle = TOTAL_FRAMES * FRAME_DURATION;
      const elapsed = currentTime % totalCycle;
      let idx = Math.floor(elapsed / FRAME_DURATION);
      if (idx >= TOTAL_FRAMES) idx = TOTAL_FRAMES - 1;
      return idx;
    }
    function startBackgroundAnimation() {
      if (bgAnimationId) cancelAnimationFrame(bgAnimationId);
      function animate() {
            if (!isPlaying) {
                bgAnimationId = requestAnimationFrame(animate);
                return;
            }
            if (!bgFramesLoaded) {
                bgAnimationId = requestAnimationFrame(animate);
                return;
            }
            const current = audioElement ? audioElement.currentTime : 0;
            const idx = getFrameIndexFromTime(current);
            drawBackgroundFrame(idx);
            bgAnimationId = requestAnimationFrame(animate);
      }
      animate();
    }
    function stopBackgroundAnimation() {
      if (bgAnimationId) {
            cancelAnimationFrame(bgAnimationId);
            bgAnimationId = null;
      }
      if (bgFramesLoaded && audioElement) {
            const idx = getFrameIndexFromTime(audioElement.currentTime);
            drawBackgroundFrame(idx);
      }
    }
    const spectrumCanvas = document.getElementById('spectrumCanvas');
    const ctx = spectrumCanvas.getContext('2d');
    const playerDiv = document.getElementById('player');
    const timeDisplay = document.getElementById('timeDisplay');
    const showcase = document.getElementById('showcase');

    function setButtonState(playing) {
      if (playing) {
            playerDiv.classList.add('playing');
      } else {
            playerDiv.classList.remove('playing');
      }
    }
    const BAR_COUNT = 25;
    const BAR_SPACING = 25;
    const FFT_SIZE = 64;
    let maxBarHeight = 80;
    let bottomBaseY = 0;
    let canvasWidth = CANVAS_W, canvasHeight = CANVAS_H;
    let barWidth = 0;
    let audioContext = null;
    let audioElement = null;
    let sourceNode = null;
    let analyserNode = null;
    let spectrumAnimationId = null;
    let isPlaying = false;
    let frequencyArray = new Uint8Array(FFT_SIZE / 2);
    let fillVideo = null;
    let fillVideoReady = false;
    let offscreenCanvas = null;
    let offscreenCtx = null;
    let videoDimensionsReady = false;
    let lastTextureUpdate = 0;
    const TEXTURE_UPDATE_INTERVAL = 50;
    let spectrumTime = 0;
    const SPECTRUM_SPEED = 0.022;
    let isAudioInitializing = false, audioInitialized = false;
    let pauseBarHeights = [];
    function getBarHeights() {
      spectrumTime += SPECTRUM_SPEED;
      if (spectrumTime > Math.PI*2) spectrumTime -= Math.PI*2;
      const minHeight = 8;
      const range = maxBarHeight - minHeight;
      const amp = 0.7;
      const heights = new Array(BAR_COUNT);
      for (let idx = 0; idx < BAR_COUNT; idx++) {
            const t = idx / BAR_COUNT;
            const val = (Math.sin(spectrumTime * 1.6 + t * Math.PI * 2.7) + 1) / 2;
            const val2 = (Math.sin(spectrumTime * 1.2 + t * Math.PI * 3.4) + 1) / 2;
            const mix = (val * 0.7 + val2 * 0.3) * amp;
            const h = minHeight + mix * range;
            heights = Math.min(maxBarHeight, Math.max(minHeight, h));
      }
      return heights;
    }
    function initFillVideo() {
      if (fillVideo) return;
      const video = document.createElement('video');
      video.loop = true; video.muted = true; video.autoplay = true; video.playsInline = true;
      video.src = FILL_VIDEO_URL;
      video.addEventListener('loadedmetadata', () => {
            if (video.videoWidth > 0) {
                offscreenCanvas = document.createElement('canvas');
                offscreenCanvas.width = video.videoWidth;
                offscreenCanvas.height = video.videoHeight;
                offscreenCtx = offscreenCanvas.getContext('2d');
                videoDimensionsReady = true;
            }
      });
      video.addEventListener('canplaythrough', () => { fillVideoReady = true; video.play().catch(()=>{}); });
      video.addEventListener('error', () => { video.src = FILL_VIDEO_FALLBACK; video.load(); });
      fillVideo = video;
      video.load();
    }
    function updateTextureIfNeeded(now) {
      if (!isPlaying) return false;
      if (!fillVideo || fillVideo.readyState < 2) return false;
      if (!offscreenCtx || !videoDimensionsReady) return false;
      if (now - lastTextureUpdate >= TEXTURE_UPDATE_INTERVAL) {
            try {
                offscreenCtx.drawImage(fillVideo, 0, 0);
                lastTextureUpdate = now;
                return true;
            } catch(e) {}
      }
      return false;
    }
    function drawBarsWithVideo(heights, startX, nowTime) {
      if (!offscreenCtx || !videoDimensionsReady || !fillVideoReady) {
            drawSolidFallback(heights, startX);
            return;
      }
      updateTextureIfNeeded(nowTime);
      const vw = offscreenCanvas.width, vh = offscreenCanvas.height;
      const sliceW = vw / BAR_COUNT;
      for (let idx = 0; idx < BAR_COUNT; idx++) {
            const x = startX + idx * (barWidth + BAR_SPACING);
            const h = heights;
            const y = bottomBaseY - h;
            if (h <= 4) continue;
            const srcX = idx * sliceW;
            ctx.save();
            ctx.beginPath();
            ctx.rect(x, y, barWidth, h);
            ctx.clip();
            try { ctx.drawImage(offscreenCanvas, srcX, 0, sliceW, vh, x, y, barWidth, h); } catch(e) {}
            ctx.restore();
            ctx.strokeStyle = '#b0f0ff';
            ctx.lineWidth = 1;
            ctx.strokeRect(x, y, barWidth, h);
            ctx.beginPath();
            ctx.moveTo(x+3, y);
            ctx.lineTo(x+barWidth-3, y);
            ctx.lineTo(x+barWidth-6, y+3);
            ctx.lineTo(x+6, y+3);
            ctx.fillStyle = 'DeepSkyBlue';
            ctx.fill();
      }
    }
    function drawSolidFallback(heights, startX) {
      for (let idx = 0; idx < BAR_COUNT; idx++) {
            const x = startX + idx * (barWidth + BAR_SPACING);
            const h = heights;
            const y = bottomBaseY - h;
            if (h <= 4) continue;
            const grad = ctx.createLinearGradient(x, y, x+barWidth, y+h);
            grad.addColorStop(0, '#1287ae');
            grad.addColorStop(1, '#064e66');
            ctx.fillStyle = grad;
            ctx.fillRect(x, y, barWidth, h);
            ctx.strokeStyle = '#8fd6ff';
            ctx.strokeRect(x, y, barWidth, h);
            ctx.beginPath();
            ctx.moveTo(x+3, y);
            ctx.lineTo(x+barWidth-3, y);
            ctx.lineTo(x+barWidth-6, y+5);
            ctx.lineTo(x+6, y+5);
            ctx.fillStyle = '#fff6cf';
            ctx.fill();
      }
    }
    function renderSpectrum() {
      const now = performance.now();
      let heights = isPlaying ? getBarHeights() : [...pauseBarHeights];
      if (!isPlaying && pauseBarHeights.length === 0) {
            heights = getBarHeights();
            pauseBarHeights = [...heights];
      }
      if(isPlaying) pauseBarHeights = [...heights];
      const totalW = BAR_COUNT * barWidth + BAR_SPACING * (BAR_COUNT - 1);
      let startX = (canvasWidth - totalW) / 2;
      if (startX < 12) startX = 12;
      const clearTop = bottomBaseY - maxBarHeight - 10;
      const clearHeight = maxBarHeight + 20;
      if (clearTop >= 0 && clearHeight > 0) {
            ctx.clearRect(0, clearTop, canvasWidth, clearHeight);
      }
      drawBarsWithVideo(heights, startX, now);
      ctx.fillStyle = 'rgba(70, 180, 210, 0.2)';
      for (let i = 0; i < BAR_COUNT; i++) {
            let x = startX + i * (barWidth + BAR_SPACING);
            ctx.fillRect(x, bottomBaseY - 2, barWidth, 1);
      }
      spectrumAnimationId = requestAnimationFrame(renderSpectrum);
    }
    function startSpectrumLoop() {
      if (spectrumAnimationId) cancelAnimationFrame(spectrumAnimationId);
      renderSpectrum();
    }
    function updateDimensions() {
      canvasWidth = spectrumCanvas.width;
      canvasHeight = spectrumCanvas.height;
      bottomBaseY = canvasHeight - 15;
      const totalSpacing = BAR_SPACING * (BAR_COUNT - 1);
      const avail = canvasWidth - totalSpacing - 40;
      barWidth = 20;
    }
    window.addEventListener('resize', () => {
      updateDimensions();
      if (!isPlaying && bgFramesLoaded && audioElement) {
            const idx = getFrameIndexFromTime(audioElement.currentTime);
            drawBackgroundFrame(idx);
      }
    });
    const lyricCanvas = document.getElementById('lyricCanvas');
    let gl = null;
    let webglProgram = null;
    let webglTexture = null;
    let webglUniforms = {};
    let currentLyricIndex = -1;
    let webglTimeAcc = 0;
    let lyricRenderId = null;
    const lrcText = `
美丽中国 - 陈思思
词:孟文豪
曲:孟文豪
壮美的北国
青山绿水如此辽阔
蓝天上白云朵朵
每寸土地都是爱的寄托
美丽中国美丽中国
绿意融融生机勃勃
处处都是绚丽的春色
美丽中国美丽中国
尊重自然坚守承诺
一起收获美好的生活
秀丽的南国
绿树红花如此婀娜
南湖上荡起碧波
每个孩子都唱起欢歌
美丽中国美丽中国
绿意融融生机勃勃
处处都是绚丽的春色
美丽中国美丽中国
尊重自然坚守承诺
一起收获美好的生活
美丽中国美丽中国
绿意融融生机勃勃
处处都是绚丽的春色
美丽中国美丽中国
尊重自然坚守承诺
一起收获美好的生活
我的话要对你诉说
我最美丽的祖国
`;
    const lyricsData = [];
    lrcText.trim().split('\n').forEach(line => {
      const match = line.match(/^\[(\d+):(\d+\.\d+)\](.*)$/);
      if (match) {
            const m = parseFloat(match);
            const s = parseFloat(match);
            const time = m * 60 + s;
            const text = match.trim();
            lyricsData.push({ time, text });
      }
    });
    function initWebGLLyric() {
      if (!lyricCanvas) return;
      gl = lyricCanvas.getContext('webgl') || lyricCanvas.getContext('experimental-webgl');
      if (!gl) return;
      const vsSource = `
                attribute vec2 a_pos;
                attribute vec2 a_uv;
                varying vec2 v_uv;
                void main() {
                  v_uv = a_uv;
                  gl_Position = vec4(a_pos, 0.0, 1.0);
                }
            `;
      const fsSource = `
                precision highp float;
                varying vec2 v_uv;
                uniform sampler2D u_text;
                uniform float u_time;
                uniform vec2 u_mouse;
                uniform float u_hover;
                void main() {
                  vec2 uv = vec2(v_uv.x, 1.0 - v_uv.y);
                  float waveX = sin(uv.y * 10.0 + u_time * 1.2) * 0.008;
                  float waveY = cos(uv.x * 8.0 - u_time * 1.0) * 0.006;
                  vec2 distorted = uv + vec2(waveX, waveY);
                  float dist = distance(distorted, u_mouse);
                  if (u_hover > 0.1 && dist < 0.25) {
                        float off = sin(dist * 15.0 - u_time * 6.0) * 0.008 * u_hover;
                        distorted += normalize(distorted - u_mouse) * off;
                  }
                  vec4 col = texture2D(u_text, distorted);
                  if (col.a < 0.05) discard;
                  float glow = smoothstep(0.3, 0.9, col.a);
                  col.rgb = mix(col.rgb, vec3(1.0, 0.96, 0.88), glow * 0.6);
                  if (u_hover > 0.1 && dist < 0.2) {
                        float halo = (1.0 - smoothstep(0.0,0.2,dist)) * u_hover * 0.5;
                        col.rgb += vec3(0.5, 0.3, 0.1) * halo;
                  }
                  gl_FragColor = col;
                }
            `;
      function compileShader(src, type) {
            const shader = gl.createShader(type);
            gl.shaderSource(shader, src);
            gl.compileShader(shader);
            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) return null;
            return shader;
      }
      const vs = compileShader(vsSource, gl.VERTEX_SHADER);
      const fs = compileShader(fsSource, gl.FRAGMENT_SHADER);
      const prog = gl.createProgram();
      gl.attachShader(prog, vs);
      gl.attachShader(prog, fs);
      gl.linkProgram(prog);
      webglProgram = prog;
      const vertices = new Float32Array([
            -1, -1, 0, 0,
            1, -1, 1, 0,
            -1,1, 0, 1,
            1,1, 1, 1
      ]);
      const vbo = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
      const a_pos = gl.getAttribLocation(prog, 'a_pos');
      const a_uv = gl.getAttribLocation(prog, 'a_uv');
      gl.enableVertexAttribArray(a_pos);
      gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 16, 0);
      gl.enableVertexAttribArray(a_uv);
      gl.vertexAttribPointer(a_uv, 2, gl.FLOAT, false, 16, 8);
      webglUniforms = {
            u_time: gl.getUniformLocation(prog, 'u_time'),
            u_text: gl.getUniformLocation(prog, 'u_text'),
            u_mouse: gl.getUniformLocation(prog, 'u_mouse'),
            u_hover: gl.getUniformLocation(prog, 'u_hover')
      };
      webglTexture = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, webglTexture);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      const textCanvas = document.createElement('canvas');
      textCanvas.width = lyricCanvas.width;
      textCanvas.height = lyricCanvas.height;
      const tctx = textCanvas.getContext('2d');
      function updateTextTexture(text) {
            tctx.clearRect(0, 0, textCanvas.width, textCanvas.height);
            tctx.letterSpacing = "4px";
            tctx.font = '65px "Long Cang","Ma Shan Zheng","ZCOOL+KuaiLe",KaiTi,STKaiti,SimHei,cursive, serif,"Microsoft YaHei","Segoe UI", "Liu Jian Mao Cao","ZCOOL QingKe HuangYou",Poppins, system-ui';
            tctx.textAlign = 'center';
            tctx.textBaseline = 'middle';
            tctx.lineWidth = 2;
            tctx.strokeStyle = '#F8F3EB';
            tctx.shadowColor = "#00BBFF";
            tctx.shadowBlur = 1;
            tctx.strokeText(text, textCanvas.width/2, textCanvas.height/2);
            tctx.fillStyle = '#BBFF00';
            tctx.fillText(text, textCanvas.width/2, textCanvas.height/2);
            gl.bindTexture(gl.TEXTURE_2D, webglTexture);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textCanvas);
      }
      let mouseX = 0.5, mouseY = 0.5, hoverValue = 0;
      lyricCanvas.addEventListener('mousemove', (e) => {
            const rect = lyricCanvas.getBoundingClientRect();
            mouseX = (e.clientX - rect.left) / rect.width;
            mouseY = 1.0 - (e.clientY - rect.top) / rect.height;
            hoverValue = Math.min(1.0, hoverValue + 0.06);
      });
      lyricCanvas.addEventListener('mouseleave', () => { hoverValue = 0; });
      let startTime = performance.now() / 1000;
      function renderLoop() {
            if (!gl || !webglProgram) return;
            if (isPlaying) {
                const now = performance.now() / 1000;
                const delta = now - startTime;
                webglTimeAcc += delta;
                startTime = now;
            } else {
                startTime = performance.now() / 1000;
            }
            const nowTime = webglTimeAcc;
            gl.viewport(0, 0, lyricCanvas.width, lyricCanvas.height);
            gl.clearColor(0, 0, 0, 0);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.useProgram(webglProgram);
            gl.uniform1f(webglUniforms.u_time, nowTime);
            gl.uniform2f(webglUniforms.u_mouse, mouseX, mouseY);
            gl.uniform1f(webglUniforms.u_hover, hoverValue);
            gl.activeTexture(gl.TEXTURE0);
            gl.bindTexture(gl.TEXTURE_2D, webglTexture);
            gl.uniform1i(webglUniforms.u_text, 0);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
            lyricRenderId = requestAnimationFrame(renderLoop);
      }
      renderLoop();
      return { updateTextTexture };
    }
    let webglUpdater = null;
    function syncLyricByTime(currentTime) {
      let idx = 0;
      for (let n = lyricsData.length-1; n>=0; n--) {
            if (currentTime >= lyricsData.time) { idx = n; break; }
      }
      if (currentTime >= lyricsData.time) idx = lyricsData.length-1;
      if (idx !== currentLyricIndex) {
            currentLyricIndex = idx;
            if (webglUpdater) webglUpdater.updateTextTexture(lyricsData.text);
      }
    }
    function formatTime(sec) {
      if (isNaN(sec)) sec = 0;
      const mins = Math.floor(sec / 60);
      const seconds = Math.floor(sec % 60);
      return `${mins}:${seconds < 10 ? '0' : ''}${seconds}`;
    }
    function updateTimeDisplay() {
      if (!audioElement) return;
      const current = audioElement.currentTime;
      const duration = audioElement.duration || 0;
      timeDisplay.textContent = `${formatTime(current)} / ${formatTime(duration)}`;
      syncLyricByTime(current);
    }
    function syncDancers(dancer) {
      const list = document.querySelectorAll('.dancer');
      list.forEach(el => {
            if(el.dataset.gif && el.dataset.png){
                el.src = dancer ? el.dataset.png : el.dataset.gif;
            }
      });
    }
    async function initAudio() {
      if (audioInitialized || isAudioInitializing) return;
      isAudioInitializing = true;
      try {
            audioElement = new Audio();
            audioElement.src = AUDIO_LOCAL;
            audioElement.preload = 'auto';
            audioElement.loop = true;
            audioElement.addEventListener('ended', () => {
                isPlaying = false;
                setButtonState(false);
                syncDancers(true);
                audioElement.currentTime = 0;
                currentLyricIndex = -1;
                if (webglUpdater) webglUpdater.updateTextTexture(lyricsData.text);
                updateTimeDisplay();
                stopBackgroundAnimation();
            });
            let hasSwitch = false;
            audioElement.addEventListener('error', () => {
                if (!hasSwitch) {
                  hasSwitch = true;
                  audioElement.src = AUDIO_FALLBACK;
                  audioElement.load();
                }
            });
            await new Promise((resolve, reject) => {
                audioElement.addEventListener('canplaythrough', resolve, { once: true });
                audioElement.addEventListener('error', reject, { once: true });
                audioElement.load();
            });
            audioContext = new (window.AudioContext || window.webkitAudioContext)();
            await audioContext.suspend();
            analyserNode = audioContext.createAnalyser();
            analyserNode.fftSize = FFT_SIZE;
            analyserNode.smoothingTimeConstant = 0.68;
            frequencyArray = new Uint8Array(analyserNode.frequencyBinCount);
            sourceNode = audioContext.createMediaElementSource(audioElement);
            sourceNode.connect(analyserNode);
            analyserNode.connect(audioContext.destination);
            audioInitialized = true;
            updateTimeDisplay();
      } catch (err) {
            console.error("音频初始化失败", err);
      } finally {
            isAudioInitializing = false;
      }
    }
    async function startPlayback() {
      if (!audioInitialized) await initAudio().then(() => _start());
      else _start();
      async function _start() {
            if (!audioElement) return;
            if (isPlaying && !audioElement.paused) return;
            try {
                if (audioContext && audioContext.state === 'suspended') {
                  await audioContext.resume();
                }
                await audioElement.play();
                isPlaying = true;
                setButtonState(true);
                syncDancers(false);
                if (!bgAnimationId && bgFramesLoaded) startBackgroundAnimation();
                if (window.timeInterval) clearInterval(window.timeInterval);
                window.timeInterval = setInterval(() => {
                  if (isPlaying && audioElement) updateTimeDisplay();
                }, 200);
            } catch (err) {
                console.warn("播放失败", err);
                isPlaying = false;
                setButtonState(false);
                syncDancers(true);
            }
      }
    }
    function pausePlayback() {
      if (audioElement && !audioElement.paused) {
            audioElement.pause();
            isPlaying = false;
            setButtonState(false);
            syncDancers(true);
            if (window.timeInterval) clearInterval(window.timeInterval);
            stopBackgroundAnimation();
      }
    }
    function togglePlayback() {
      vids.forEach(vid => !audioElement.paused ? vid.pause() : vid.play());
      if (isPlaying && audioElement && !audioElement.paused) {
            pausePlayback();
      } else {
            startPlayback();
      }
    }
    async function attemptAutoPlay() {
      await initAudio();
      startSpectrumLoop();
      try {
            if (audioContext && audioContext.state === 'suspended') await audioContext.resume();
            await audioElement.play();
            isPlaying = true;
            setButtonState(true);
            syncDancers(false);
            if (!bgAnimationId && bgFramesLoaded) startBackgroundAnimation();
            if (window.timeInterval) clearInterval(window.timeInterval);
            window.timeInterval = setInterval(() => {
                if (isPlaying && audioElement) updateTimeDisplay();
            }, 200);
      } catch (e) {
            setButtonState(false);
            isPlaying = false;
            syncDancers(true);
      }
    }
    let fs = true,fsTimer;
    fullscreen.onclick = ()=>{
      if(fs){
            fullscreen.innerText = '退出全屏';
            papa.requestFullscreen();
      }else{
            fullscreen.innerText = '全屏欣赏';
            document.exitFullscreen();
      }
      fs = !fs;
    };
    papa.addEventListener('mousemove', () => {
      clearTimeout(fsTimer);
      fullscreen.style.opacity = '1';
      fsTimer = setTimeout(() => fullscreen.style.opacity = '0', 2500);
    });
    document.addEventListener('visibilitychange', () => {
      if (document.hidden) {
            if (!audioElement.paused) audioElement.pause();
      } else {
            if (audioElement.paused && !audioElement.ended) audioElement.play().catch(()=>{});
      }
    });
    ['contextmenu', 'dragstart', 'selectstart'].forEach(ev =>
      papa.addEventListener(ev, (e) => { e.preventDefault(); })
    );
    async function init() {
      spectrumCanvas.width = CANVAS_W;
      spectrumCanvas.height = CANVAS_H;
      bgCanvas.width = CANVAS_W;
      bgCanvas.height = CANVAS_H;
      updateDimensions();
      initFillVideo();
      loadBackgroundFrames();
      await initAudio();
      const webglObj = initWebGLLyric();
      if (webglObj) webglUpdater = webglObj;
      if (webglUpdater) webglUpdater.updateTextTexture(lyricsData.text);
      playerDiv.addEventListener('click', togglePlayback);
      setButtonState(false);
      isPlaying = false;
      syncDancers(true);
      attemptAutoPlay();
      vids.forEach(vid => !audioElement.paused ? vid.pause() : vid.play());
    }
    init();
})();
</script>
</body>
</html>
-->

杨帆 发表于 2026-6-13 13:49

梦江南 发表于 2026-6-13 10:16
可能是我的电脑问题,不用辛苦了。

是什么原因?我这显示正常呀

杨帆 发表于 2026-6-13 13:58

也曾年轻 发表于 2026-6-13 13:49
本帖最后由 杨帆 于 2026-6-13 13:57 编辑




作了初始化处理,现在老师能看到视频吗?我这显示正常

梦江南 发表于 2026-6-13 14:53

也曾年轻 发表于 2026-6-13 13:49
本帖最后由 杨帆 于 2026-6-13 14:25 编辑




背景MP4看到了,很漂亮。

也曾年轻 发表于 2026-6-13 15:29

杨帆 发表于 2026-6-13 13:58
作了初始化处理,现在老师能看到视频吗?我这显示正常

23#应该是正常的样子。

也曾年轻 发表于 2026-6-13 15:30

梦江南 发表于 2026-6-13 14:53
背景MP4看到了,很漂亮。

就是那视频没显示的问题。

梦江南 发表于 2026-6-13 16:16

也曾年轻 发表于 2026-6-13 15:30
就是那视频没显示的问题。

去源代码看过,有2个MP4.

也曾年轻 发表于 2026-6-13 16:39

梦江南 发表于 2026-6-13 16:16
去源代码看过,有2个MP4.

前一个http 后一个飘红旗是 https,前一个不显示。

梦江南 发表于 2026-6-13 18:32

也曾年轻 发表于 2026-6-13 16:39
前一个http 后一个飘红旗是 https,前一个不显示。

如果前后换一下,一个就会显示了吗?

也曾年轻 发表于 2026-6-13 18:39

梦江南 发表于 2026-6-13 18:32
如果前后换一下,一个就会显示了吗?

我把它下载下来然后上传换了个地址

梦江南 发表于 2026-6-13 19:32

也曾年轻 发表于 2026-6-13 18:39
我把它下载下来然后上传换了个地址

哦,是地址不对。

红影 发表于 2026-6-13 22:22

杨帆 发表于 2026-6-13 13:45
欢迎影子欣赏~能看到视频吗?

是飘动的红旗么,能看到,但有点暗。

杨帆 发表于 2026-6-13 22:43

也曾年轻 发表于 2026-6-13 18:39
我把它下载下来然后上传换了个地址

没注意呢,把那个http视频下载后上传换了新地址才显示了?老师您辛苦了{:4_180:}

杨帆 发表于 2026-6-13 22:46

本帖最后由 杨帆 于 2026-6-13 23:16 编辑

红影 发表于 2026-6-13 22:22
是飘动的红旗么,能看到,但有点暗。
不是,第二页年轻老师换了那个未显示视频的地址,应看到2个视频呀

第一页那个http地址视频仅我这显示正常,现在换上年轻老师的https地址,应该大家都可以看到了

小辣椒 发表于 2026-6-14 22:06

这个背景视频漂亮的,给整体制作加了许多出彩的效果{:4_199:}

小辣椒 发表于 2026-6-14 22:09

欣赏杨帆精彩的制作,{:4_199:}

感觉我的那个五星红旗的视频连接可以不用加的,没有什么作用,反而视频多出来会卡

杨帆 发表于 2026-6-14 22:10

小辣椒 发表于 2026-6-14 22:06
这个背景视频漂亮的,给整体制作加了许多出彩的效果

问好小辣椒,谢谢鼓励,祝开心{:4_204:}

杨帆 发表于 2026-6-14 22:15

小辣椒 发表于 2026-6-14 22:09
欣赏杨帆精彩的制作,

感觉我的那个五星红旗的视频连接可以不用加的,没有什么作用,反而视频 ...

谢谢小辣椒的建议,可你的那个五星红旗的视频挺好的呀{:4_187:}
页: 1 [2] 3
查看完整版本: 美 丽 中 国