杨帆 发表于 2026-6-26 16:52

愿这夏天烦恼都远走

本帖最后由 杨帆 于 2026-6-26 17:09 编辑 <br /><br /><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="referrer" content="never"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<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");
.pa{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('https://638183.freep.cn/638183/small/opic.jpg') no-repeat center/cover;font-family:"ZCOOL KuaiLe","Ma Shan Zheng","Long Cang","华文行楷","SimHei","Arial","sans-serif";--state:running;}
.bg-layer{position:absolute;inset:0;background-image:url("https://pic1.imgdb.cn/item/6a3d10a8bb21102f81d51401.png");background-repeat:no-repeat;background-position:center;background-size:100% 100%;z-index:0;transition:background-image 0.2s ease;}
.pa.play .bg-layer{background-image:url("https://pic1.imgdb.cn/item/69b4c75b3c25a1c98038839d.gif");}
#svgObj{position:absolute;left:50%;top:15%;transform:translateX(-50%);width:100vw;height:40vw;z-index:5;fill:none;stroke:url(#grdWave);stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:2 4;stroke-dashoffset:0;opacity:.45;animation:pMove 8s ease-in-out infinite alternate var(--state);}
@keyframes pMove{to{stroke-dashoffset:-180;}}
.vid{position:absolute;z-index:2;left:-10%;top:-10%;width:120%;height:120%;object-fit:cover;pointer-events:none;object-position:center;mix-blend-mode:screen;mask:linear-gradient(to bottom,red 20%,transparent 58%);-webkit-mask:linear-gradient(to bottom,red 20%,transparent 58%);}
#msvg{position:absolute;z-index:12;right:50px;top:50px;width:120px;height:120px;display:block;cursor:pointer;animation:rotate 4s 0.5s linear infinite var(--state);}
#msvg:hover { filter: unset !important; }
@keyframes rotate{to{transform:rotate(360deg);}}
#lyricCanvas{position:absolute;left:20%;top:5%;width:900px;height:180px;transform:perspective(800px) rotateY(20deg);background:transparent;z-index:5;filter:drop-shadow(0 var(--shadow-offset) 0 rgba(189,183,107,.75));--shadow-offset:clamp(580px, 45vh, 680px);}
#wrapper{position:absolute;left:20%;bottom:30px;font:500 60px/0px "Long Cang","Ma Shan Zheng","STKaiti";letter-spacing:4px;color:#ff0000;white-space:pre;width:860px;height:70px;text-align:center;filter:drop-shadow(#fff 1px 0 0) drop-shadow(#fff 0 1px 0) drop-shadow(#fff -1px 0 0) drop-shadow(#fff 0 -1px 0);z-index:6;}
.char{display:inline-block;padding:0px 2px;opacity:0;transform:translate(var(--x), var(--y)) rotate(270deg);animation:fadeIn 1.5s var(--delay) forwards var(--state),flas 0.5s linear infinite var(--state);}
@keyframes fadeIn{100%{transform:translate(0, 0%);opacity:1;}}
@keyframes flas{100%{filter:hue-rotate(360deg);}}
#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;}
#statusDisplay{position:absolute;z-index:3;font-size:1.5em;font-weight:50;left:65%;top:25%;color:#fff;}
</style>
</head>
<body>
<div id="pa" class="pa">
<div id="wrapper"></div>
<div id="fullscreen">全屏欣赏</div>
<div id="statusDisplay">播放中: -2:20</div>
<canvas id="lyricCanvas" width="900" height="180"></canvas>
<audio id="aud" src="https://i.uik.cc/view.php/8c35c640c04dbae31d633f3be14c9a9c.mp3" loop autoplay></audio>
<video class="vid" src="https://img2.tukuppt.com/video_show/2418175/01/04/62/614ade273f6d1.mp4" autoplay loop muted></video>
<div class="bg-layer"></div>
<svg id="svgObj" viewBox="0 0 160 90">
<defs>
<linearGradient id="grdWave">
<stop offset="0" stop-color="#072afc"></stop>
<stop offset="0.15" stop-color="#1976D2"></stop>
<stop offset="1" stop-color="#2196F3"></stop>
</linearGradient>
</defs>
<symbol id="pb">
<path d='M0 45 C40 0 120 90 160 45'></path>
</symbol>
<use href="#pb" x="-5" y="0"></use>
<use href="#pb" x="0" y="5"></use>
<use href="#pb" x="5" y="10"></use>
</svg>
<svg id="msvg" width="400" height="400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400"><title id="svgTip">暂停</title>
<defs id="defs">
<radialGradient id="grd" cx="0.25" cy="0.25" r="0.25">
<stop offset="5%" stop-color="red"/>
<stop offset="30%" stop-color="lightgreen"/>
<stop offset="100%" stop-color="darkred"/>
</radialGradient>
<symbol id="sy" viewBox="0 0 400 400">
<circle cx="150" cy="20" r="20" fill="url(#grd)" stroke="pink" stroke-width="2"/>
<circle cx="150" cy="100" r="20" fill="url(#grd)" stroke="pink" stroke-width="2"/>
<circle cx="150" cy="180" r="20" fill="url(#grd)" stroke="pink" stroke-width="2"/>
</symbol>
</defs>
<use href="#sy"/>
<use href="#sy" transform="rotate(60, 200 200)"/>
<use href="#sy" transform="rotate(120, 200 200)"/>
<use href="#sy" transform="rotate(180, 200 200)"/>
<use href="#sy" transform="rotate(240, 200 200)"/>
<use href="#sy" transform="rotate(300, 200 200)"/>
</svg>
</div>
<script>
const msvg = document.getElementById('msvg');
const wave = document.getElementById('svgObj');
const paBox = document.getElementById('pa');
const vid = document.querySelector('.vid');
const statusDisplay = document.getElementById('statusDisplay');
const audioPlayer = document.getElementById('aud');
const svgTip = document.getElementById('svgTip');

let isPaused = true;

function togglePlayPause() {
if (isPaused) {
    isPaused =false ;
    paBox.style.animationPlayState = 'running';   
    vid.play();
    audioPlayer.play();
    paBox.classList.add('play');
    statusDisplay.innerHTML = `<span style="color:#CC00FF">播放中:</span><span style="color:#FF0088">${formatTime(-(audioPlayer.duration-audioPlayer.currentTime))}</span>`;
} else {
    isPaused = true;
    paBox.style.animationPlayState = 'paused';
    vid.pause();
    audioPlayer.pause();
    paBox.classList.remove('play');
    statusDisplay.textContent = '已暂停';
}
   paBox.style.setProperty('--state', isPaused ? 'paused' : 'running');
   svgTip.textContent = isPaused ? "播放" : "暂停";
   
}

msvg.addEventListener('click', (e) => {
      e.stopPropagation();
      togglePlayPause();
               
    });

function formatTime(seconds) {
const abs = Math.abs(seconds);
const m = Math.floor(abs/60);
const s = Math.floor(abs%60);
return `${seconds<0?'-':''}${m}:${s<10?'0':''}${s}`;
}

function renderPlayTime() {
      if(!audioPlayer.duration) return;
      const rem = audioPlayer.duration - audioPlayer.currentTime;
      statusDisplay.innerHTML = `<span style="color:#CC00FF">播放中:</span><span style="color:#FF0088">${formatTime(-rem)}</span>`;
}

(function() {
    const lyricCanvas = document.getElementById('lyricCanvas');
    const toggleBtn = document.getElementById('msvg');

    let gl = null;
    let webglProgram = null;
    let webglTexture = null;
    let webglUniforms = {};
    let webglTimeAcc = 0;
    let lyricRenderId = null;

    letisPaused = true;
    const waveSpeed = 1.0;

    let showText = "愿这夏天烦恼都远走";

    function initWebGLLyric() {
      gl = lyricCanvas.getContext('webgl') || lyricCanvas.getContext('experimental-webgl');
      if (!gl) {
            alert("浏览器不支持WebGL,无法展示水波文字");
            return null;
      }

      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;
            uniform float u_speed;
            void main() {
                vec2 uv = vec2(v_uv.x, 1.0 - v_uv.y);
                float t = u_time * u_speed;
                float waveX = sin(uv.y * 10.0 + t * 1.2) * 0.008;
                float waveY = cos(uv.x * 8.0 - t * 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 - t * 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'),
            u_speed: gl.getUniformLocation(prog, 'u_speed')
      };

      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 = "6px";
            tctx.font = '72px "Long Cang","Ma Shan Zheng","ZCOOL KuaiLe",KaiTi,SimHei,cursive';
            tctx.textAlign = 'center';
            tctx.textBaseline = 'middle';
            tctx.lineWidth = 2;
            tctx.strokeStyle = '#F8F3EB';
            tctx.shadowColor = "#00BBFF";
            tctx.shadowBlur = 2;
            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;
            const now = performance.now() / 1000;
            const delta = now - startTime;
            if(isPaused){
                webglTimeAcc += delta * waveSpeed;
            }
            startTime = now;

            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, webglTimeAcc);
            gl.uniform1f(webglUniforms.u_speed, isPaused ? waveSpeed : 0);
            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 };
    }

    function bindControlButtons(){
      toggleBtn.onclick = ()=>{      
            isPaused = !isPaused;
         
      };
    }

    function init() {      
      const webglUpdater = initWebGLLyric();
      bindControlButtons();
      if (webglUpdater) {
            webglUpdater.updateTextTexture(showText);
      }
    }
    init();
   
})();

window.addEventListener('load', ()=>{
    togglePlayPause();
})

const gc = `李郁花 - 愿这夏天烦恼都远走
李郁花 - 愿这夏天烦恼都远走
愿夏天的风吹走你忧愁
好事全跟着走坏事顺水流
人生不止每天搬砖没够
还有鲜花美酒好朋友
愿你一身疲惫让风吹走
别为了 没发生的 事而担忧
你要多给自己一些温柔
不要总是紧皱着眉头
人生短短三万天
你要过好每一天
能让自己开心就开心一点
得失只不过弹指间
别让遗憾成永远
潇潇洒洒好好活一遍
愿你一身疲惫让风吹走
别为了没发生的事而担忧
你要多给自己一些温柔
不要总是紧皱着眉头
人生短短三万天
你要过好每一天
能让自己开心就开心一点
得失只不过弹指间
别让遗憾成永远
潇潇洒洒好好活一遍
人生短短三万天
你要过好每一天
能让自己开心就开心一点
得失只不过弹指间
别让遗憾成永远
潇潇洒洒好好活一遍

`;
const gcAr = lrc2HC(gc);
let curkey = 1, isSeeking = false;
aud.ontimeupdate = () => {
const currentTime = audioPlayer.currentTime;
if(!audioPlayer.paused && audioPlayer.duration) renderPlayTime();
if(curkey > gcAr.length - 1) return;
if(aud.currentTime >= gcAr) {
const gap = gcAr?. ?? 0 - gcAr;
showLrc(gcAr, wrapper, gap);
}
};
aud.onended = () => {
curkey = 1;
aud.play();
}
aud.onseeked = () => calcKey();
function lrc2HC(text) {
let lrcAr = [];
let ar = text.trim().split('\n');
ar.sort();
let reg = /\[(\d+)[.:](\d+)[.:](\d+)\](.*)/;
ar.forEach(item => {
if(reg.test(item)) {
let result = item.match(reg);
let tmsg = parseInt(result) * 60 + parseInt(result) + parseInt(result) / 1000;
lrcAr.push(.trim()]);
}
});
return lrcAr ? lrcAr : ;
};
function calcKey() {
for (let j = 0; j < gcAr.length; j++) {
if (aud.currentTime <= gcAr) {
curkey = j - 1;
break;
}
}
if (curkey < 0) curkey = 0;
if (curkey > gcAr.length - 1) curkey = gcAr.length - 1;
let time = gcAr?. ?? 0 - gcAr;
isSeeking = false;
showLrc(gcAr, wrapper, time);
}
function showLrc(str, targetElm, time) {
if(isSeeking) return;
targetElm.innerHTML = '';
const chars = str.split('').map(c => c === ' ' ? ' ' : c);
const frg = document.createDocumentFragment();
chars.forEach((char, idx) => {
const span = document.createElement('span');
span.innerHTML = char;
span.classList.add('char');
const x = Math.random() * (Math.random() > 0.5 ? -600 : 600);
const y = Math.random() * (Math.random() > 0.5 ? 0 : 0);
span.style.cssText += `
color: #${Math.random().toString(11).substring(2,8)};
--x: ${x}px;
--y: ${y}px;
--delay: ${Math.random() * 0.5}s;
`;
frg.appendChild(span);
});
targetElm.appendChild(frg);
curkey ++;
setTimeout(() =>isSeeking = false, time);
}
let fs = true,fsTimer;
fullscreen.onclick = ()=>{
if(fs){
    fullscreen.innerText = '退出全屏';
    pa.requestFullscreen();
}else{
    fullscreen.innerText = '全屏欣赏';
    document.exitFullscreen();
}
fs = !fs;
};
pa.addEventListener('mousemove', () => {
clearTimeout(fsTimer);
fullscreen.style.opacity = '1';
fsTimer = setTimeout(() => fullscreen.style.opacity = '0', 2500);
});
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
    if (!aud.paused) aud.pause();
} else {
    if (aud.paused && !aud.ended) aud.play().catch(()=>{});
}
});

['contextmenu', 'dragstart', 'selectstart'].forEach(ev =>
pa.addEventListener(ev, (e) => { e.preventDefault(); })
);
msvg.onanimationiteration = () => {
msvg.style.setProperty('filter', `hue-rotate(${60 + Math.random() * 300}deg)`);
};
</script>
</body>
</html>

魏淑芬 发表于 2026-6-26 16:58

{:4_335:}好听,凉爽,欣赏,点赞!

魏淑芬 发表于 2026-6-26 16:59

{:4_335:}好听,凉爽,欣赏,点赞!

魏淑芬 发表于 2026-6-26 17:00

怎么回复了两条呢?{:4_203:}

霜染枫丹 发表于 2026-6-26 18:19

很精美的制作,很好听的歌声,喜欢!祝扬帆制作愉快~~{:4_204:}{:4_190:}

梦江南 发表于 2026-6-26 18:42

全屏欣赏标题效果的倒影全看到,更漂亮。{:4_187:}

梦江南 发表于 2026-6-26 18:43

歌曲好听,制作精美,谢谢杨帆的精彩分享!{:4_204:}

杨帆 发表于 2026-6-26 18:46

魏淑芬 发表于 2026-6-26 17:00
怎么回复了两条呢?

呵呵,多多益善呀,谢谢鼓励,祝魏淑芬老师夏安{:4_204:}

杨帆 发表于 2026-6-26 18:47

霜染枫丹 发表于 2026-6-26 18:19
很精美的制作,很好听的歌声,喜欢!祝扬帆制作愉快~~

谢谢鼓励,祝枫丹老师夏安{:4_204:}

杨帆 发表于 2026-6-26 18:48

梦江南 发表于 2026-6-26 18:42
全屏欣赏标题效果的倒影全看到,更漂亮。

挺仔细呢,谢谢鼓励,祝江南老师夏安{:4_204:}

红影 发表于 2026-6-26 21:39

漂亮的水波纹标题字,以及很有特点的歌词同步。
欣赏杨帆好帖{:4_199:}

姚云裳 发表于 2026-6-27 00:48


很精美的制作,欣赏并学习

杨帆 发表于 2026-6-27 15:30

姚云裳 发表于 2026-6-27 00:48
很精美的制作,欣赏并学习

问好云裳,谢谢鼓励,祝夏安{:4_204:}
页: [1]
查看完整版本: 愿这夏天烦恼都远走