亚伦影音工作室 发表于 2025-11-23 15:03

特效歌词 #多情的小雨无情的风-王思雨#

本帖最后由 亚伦影音工作室 于 2025-11-23 20:53 编辑 <br /><br /><style>
    #bj {
      position: relative;
      width: 1286px;
      height: 720px;
      margin-left: -300px;
      margin-top: 0;
       overflow: hidden;z-index:12345;
            background:url(https://pic1.imgdb.cn/item/67162d12d29ded1a8c2f45cf.jpg)no-repeat center/cover;
   
    }
    canvas {
position: absolute;
      width: 100%;
      height: 100%;
      display: block;
      cursor: pointer;
      transition: transform 0.3s ease;
      margin-top: -50px;margin-left: -120px;
    }
    canvas:hover {
      transform: scale(1.05);
    }

    .lyric-preview { opacity: 0;
      position: absolute;
      top: 40px;
      left: 50%;
      transform: translateX(-50%);
      color: blue;
      font-size: 18px;
      text-align: center;
      width: 80%;
      z-index: 5;
      cursor: pointer; /* 提示可点击 */
      padding: 10px;
      border-radius: 8px;
      transition: background-color 0.2s ease;
    }
    .lyric-preview:hover {
   color: #00ff00;
    }
    .prev-lyric {
      opacity: 0.6;
      margin-bottom: 8px;
      transition: opacity 0.2s ease;
    }
    .current-lyric {
      font-size: 22px;
      font-weight: bold;
      color: #ff00ff;
      transition: opacity 0.2s ease;
    }
    .next-lyric {
      opacity: 0.6;
      margin-top: 8px;
      transition: opacity 0.2s ease;
    }
    .lyric-preview:active .current-lyric {
      opacity: 0.9;
    }
#player {
        position: absolute;z-index: 40;
        left:5%;
        bottom: 50px;
        width: 150px;
        height: 150px;
         opacity: 1;
        transition: .4s;
display: grid;
        place-items: center;
        --sp1: 0; --sp2: 1;
}
#player::before, #player::after {
        position: absolute;
        content: '';
        cursor: pointer;
        transition: .4s;
}
#player::before {width: 150px;height: 150px;background:url(https://pic.imgdb.cn/item/65f0d8669f345e8d03ff5c34.png)no-repeat center/cover;
        opacity: var(--sp1);}
#player::after {width: 150px;height: 150px;background:url(https://pic.imgdb.cn/item/65f0d8299f345e8d03ff0b31.gif)no-repeat center/cover;
        opacity: var(--sp2);}
</style>

<div id="bj">
    <div class="lyric-preview" id="lyricPreview">
      <div class="prev-lyric" id="prevLyric"></div>
      <div class="current-lyric" id="currentLyric"></div>
      <div class="next-lyric" id="nextLyric"></div>
    </div>
<div id="player" title="暂停/播放" ></div>
    <canvas id="glcanvas" width="900" height="420"></canvas>
    <audio id="audio" src="https://s2.cldisk.com/sv-w8/audio/f7/23/f0/8da618a5428a205837d91838096d3cdf/audio.mp3" loop autoplay></audio>
</div>

<script>
    const state = {
      currentLyricIndex: 0,
      isAudioEnabled: true,
      isPlaying: false,
      mouseX: 0,
      mouseY: 0,
      isHovering: false,
      lyrics: [],
      hoverValue: 0,
      hoverSpeed: 0.005, // 降低hover动画速度,更流畅
      lastMouseMoveTime: 0,
      throttleDelay: 100 // 鼠标事件节流延迟
    };

    const elements = {
      canvas: document.getElementById('glcanvas'),
      audio: document.getElementById('audio'),
      lyricPreview: document.getElementById('lyricPreview'), // 歌词容器
      prevLyric: document.getElementById('prevLyric'),
      currentLyric: document.getElementById('currentLyric'),
      nextLyric: document.getElementById('nextLyric')
    };

    // ===================== 初始化检测 =====================
    function initCheck() {
      // WebGL兼容性检测
      const gl = elements.canvas.getContext('webgl') || elements.canvas.getContext('experimental-webgl');
      if (!gl) {
            state.isAudioEnabled = false; //
            return null;
      }
      return gl;
    }

    // ===================== LRC歌词解析 =====================
    function parsePureLRC(lrcText) {
      const lines = [];
      const lrcLines = lrcText.split('\n')
            .map(line => line.trim())
            .filter(line => line && !line.includes('●') && !line.includes('谢谢欣赏'));

      for (const line of lrcLines) {
            const timeRegex = /\[(\d{2}):(\d{2})(?:\.(\d{1,3}))?\]/g;
            const text = line.replace(timeRegex, '').trim();
            let timeMatch;

            while ((timeMatch = timeRegex.exec(line)) !== null) {
                const minutes = parseInt(timeMatch);
                const seconds = parseInt(timeMatch);
                const ms = timeMatch ? parseInt(timeMatch.padEnd(3, '0')) : 0;
                const time = minutes * 60 + seconds + ms / 1000;

                if (text) {
                  lines.push({ time, text });
                }
            }
      }

      return lines.sort((a, b) => a.time - b.time);
    }

    // ===================== 歌词跳转 =====================
    function jumpToLyricByText(clickText) {
      if (!clickText.trim()) return;
      const targetLyric = state.lyrics.find(lyric => lyric.text === clickText.trim());
      if (!targetLyric) return;
      elements.audio.currentTime = targetLyric.time;
      const targetIndex = state.lyrics.findIndex(lyric => lyric.text === clickText.trim());
      if (targetIndex !== -1) {
            state.currentLyricIndex = targetIndex;
            elements.prevLyric.textContent = state.lyrics?.text || '';
            elements.currentLyric.textContent = state.lyrics.text;
            elements.nextLyric.textContent = state.lyrics?.text || '';
            if (window.render && window.render.updateTextTexture) {
                window.render.updateTextTexture(state.lyrics.text);
            }
      }
    }

    // ===================== WebGL渲染 =====================
    function initWebGL(gl) {
      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 vertexShaderSource = `
            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 fragmentShaderSource = `
            precision highp float;
            varying vec2 v_uv;
            uniform sampler2D u_text;
            uniform float u_time;
            uniform vec2 u_mouse;
            uniform float u_hover;

            float random(vec2 st) {
                return fract(sin(dot(st.xy, vec2(12.9898,78.233)))*43758.5453123);
            }

            float noise(vec2 st) {
                vec2 i = floor(st);
                vec2 f = fract(st);
                float a = random(i);
                float b = random(i + vec2(1.0,0.0));
                float c = random(i + vec2(0.0,1.0));
                float d = random(i + vec2(1.0,1.0));
                vec2 u = f*f*(3.0-2.0*f);
                return mix(a,b,u.x) + (c-a)*u.y*(1.0-u.x) + (d-b)*u.x*u.y;
            }

            void main() {
                vec2 correctedUV = vec2(v_uv.x, 1.0-v_uv.y);
                float strength = smoothstep(0.2,1.0,correctedUV.y);
                float noiseTime = u_time * 0.3;
                float n = noise(vec2(correctedUV.x*5.0, (correctedUV.y*2.0 - noiseTime)*2.0));
               
                float melt = n * 0.4 * (correctedUV.y);
                float dist = distance(correctedUV, u_mouse);
            
                float hoverWave = 0.0;
                if (u_hover > 0.1) {
                  hoverWave = sin(dist*12.0 - u_time*6.0)*0.08*u_hover*exp(-dist*3.5) +
                               sin(dist*20.0 - u_time*10.0)*0.04*u_hover*exp(-dist*5.0);
                }
                  
                vec2 hoverDistort = normalize(correctedUV - u_mouse) * hoverWave * (1.0 + sin(u_time*2.0)*0.1);
                vec2 finalUV = vec2(
                  correctedUV.x + melt*0.3 + hoverDistort.x,
                  correctedUV.y - melt*0.8 + hoverDistort.y
                );

                vec4 col = texture2D(u_text, finalUV);
                if (col.a > 0.1) {
                  float glow = smoothstep(0.8,1.0,col.a);
                  vec3 spectrumColor = vec3(correctedUV.y, abs(sin(u_time + correctedUV.x*5.0)), 1.0-correctedUV.y);
                  
                  if (u_hover > 0.1) {
                        float hoverIntensity = 1.0 - smoothstep(0.0,0.1,dist);
                        float pulseEffect = 0.99 + 0.1*sin(u_time*4.0 + dist*8.0);
                        vec3 goldColor = vec3(0.99, 0.99+0.8*pulseEffect, 0.2+0.2*sin(u_time*3.0));
                        vec3 blueColor = vec3(0.99+0.99*sin(u_time*2.0 + dist*6.0), 0.99+0.8*pulseEffect, 0.5);
                        spectrumColor = mix(spectrumColor, mix(goldColor, blueColor, 0.99), hoverIntensity*u_hover*0.99);
                        glow += hoverIntensity*u_hover*0.99;
                  }
                  
                  col.rgb = mix(col.rgb, spectrumColor, 0.99*glow);
                  
                  // 优化粒子效果
                   if (u_hover > 0.1 && dist < 0.2) {
                        float particles = noise(correctedUV*15.0 + u_time*2.0);
                        if (particles > 0.85) col.rgb += vec3(1.0,0.8,0.4)*(particles-0.85)*8.0*u_hover;
                        
                        float sparkles = noise(correctedUV*30.0 + u_time*4.0);
                        if (sparkles > 0.92 && dist < 0.15) col.rgb += vec3(0.9,0.9,1.0)*(sparkles-0.92)*6.0*u_hover;
                  }
                }
                     
                if (u_hover > 0.1) {
                  float ambientGlow = 1.0 - smoothstep(0.0,0.4,dist);
                  float auraEffect = sin(dist*6.0 - u_time*3.0)*0.2 + 0.8;
                  vec3 auraColor = vec3(
                        0.15+0.1*sin(u_time*1.5),
                        0.1+0.1*sin(u_time*2.0+1.0),
                        0.2+0.15*sin(u_time*1.2+2.0)
                  );
                  col.rgb += auraColor*ambientGlow*u_hover*auraEffect;
                  
                  float outerHalo = 1.0 - smoothstep(0.2,0.5,dist);
                  col.rgb += vec3(0.08,0.04,0.12)*outerHalo*u_hover*0.3;
                }
               
                gl_FragColor = col;
            }
      `;
      const vs = compileShader(vertexShaderSource, gl.VERTEX_SHADER);
      const fs = compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER);
      const program = gl.createProgram();
      gl.attachShader(program, vs);
      gl.attachShader(program, fs);
      gl.linkProgram(program);
      const quad = new Float32Array([
          -1, -1, 0, 0,
            1, -1, 1, 0,
            -1, 1, 0, 1,
            1, 1, 1, 1
      ]);
      const buf = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, buf);
      gl.bufferData(gl.ARRAY_BUFFER, quad, gl.STATIC_DRAW);
      const a_pos = gl.getAttribLocation(program, 'a_pos');
      const a_uv = gl.getAttribLocation(program, '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);
      const uniforms = {
            u_time: gl.getUniformLocation(program, 'u_time'),
            u_text: gl.getUniformLocation(program, 'u_text'),
            u_mouse: gl.getUniformLocation(program, 'u_mouse'),
            u_hover: gl.getUniformLocation(program, 'u_hover')
      };
      const textCanvas = document.createElement('canvas');
      const tctx = textCanvas.getContext('2d');
      textCanvas.width = elements.canvas.width;
      textCanvas.height = elements.canvas.height;

      const textTex = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, textTex);
      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);
      function updateTextTexture(text) {if (!audio.paused) {
            tctx.clearRect(1, 1, textCanvas.width, textCanvas.height);
            tctx.fillStyle = '#000';
            tctx.font = '800 30px 微软雅黑';
            tctx.textAlign = 'center';
            tctx.textBaseline = '800';
            tctx.fillText(text || '', textCanvas.width / 2, textCanvas.height / 2);
            
            gl.bindTexture(gl.TEXTURE_2D, textTex);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textCanvas);
      }
}
      // 绘制函数
      function draw(t) {
            if (!state.isAudioEnabled) return;
            if (state.isHovering && state.hoverValue < 1.0) {
                state.hoverValue = Math.min(1.0, state.hoverValue + state.hoverSpeed);
            } else if (!state.isHovering && state.hoverValue > 0.0) {
                state.hoverValue = Math.max(0.0, state.hoverValue - state.hoverSpeed);
            }
            gl.viewport(0, 0, elements.canvas.width, elements.canvas.height);
            gl.clear(gl.COLOR_BUFFER_BIT);
            gl.useProgram(program);
            const time = t * 0.0005;
            gl.uniform1f(uniforms.u_time, time);
            gl.uniform2f(uniforms.u_mouse, state.mouseX, state.mouseY);
            gl.uniform1f(uniforms.u_hover, state.hoverValue);
            gl.activeTexture(gl.TEXTURE0);
            gl.bindTexture(gl.TEXTURE_2D, textTex);
            gl.uniform1i(uniforms.u_text, 0);

            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

          requestAnimationFrame(draw);
      }

      return { updateTextTexture, draw};
    }

    // ===================== 歌词同步 =====================
    function updateLyric() {
      if (!state.isAudioEnabled || !state.lyrics.length) return;
      const currentTime = elements.audio.currentTime;
      const { lyrics } = state;
      for (let i = 0; i < lyrics.length; i++) {
            const currentLyricTime = lyrics.time;
            const nextLyricTime = i < lyrics.length - 1 ? lyrics.time : Infinity;
            if (currentTime >= currentLyricTime && currentTime < nextLyricTime && state.currentLyricIndex !== i) {
                state.currentLyricIndex = i;
                if (window.render && window.render.updateTextTexture) {
                  window.render.updateTextTexture(lyrics.text);
                }
                // 更新歌词预览
                elements.prevLyric.textContent = lyrics?.text || '';
                elements.currentLyric.textContent = lyrics.text;
                elements.nextLyric.textContent = lyrics?.text || '';
                break;
            }
      }

       requestAnimationFrame(updateLyric);
    }

    // ===================== 事件绑定 =====================
    function bindEvents(gl) {
      window.addEventListener('resize', () => {
            if (!gl) return;
            const width = elements.canvas.parentElement.clientWidth * 0.95;
            const height = elements.canvas.parentElement.clientHeight * 0.6;
            elements.canvas.width = width;
            elements.canvas.height = height;
      });
      elements.canvas.addEventListener('mousemove', (e) => {if (!audio.paused) {
            const now = Date.now();
            if (now - state.lastMouseMoveTime < state.throttleDelay) return;
            state.lastMouseMoveTime = now;

            if (state.isAudioEnabled) {
                const rect = elements.canvas.getBoundingClientRect();
                state.mouseX = (e.clientX - rect.left) / rect.width;
                state.mouseY = 1.0 - (e.clientY - rect.top) / rect.height;
                state.isHovering = true;
            }
       } });
      elements.canvas.addEventListener('mouseleave', () => {
            state.isHovering = false;
      });
      elements.lyricPreview.addEventListener('click', (e) => {
            const target = e.target;
            if (target.classList.contains('prev-lyric') || target.classList.contains('current-lyric') || target.classList.contains('next-lyric')) {
                const clickText = target.textContent;
                jumpToLyricByText(clickText);
            }
      });
    }

    // ===================== 初始化 =====================
    async function init() {
      // LRC歌词文本
      const pureLRCText = `
多情的小雨无情的风-王思雨
词:崔伟立
曲:崔伟立
编曲:孔德明
笛子:郭忠合
和声:慧慧
录音:孔德明
混音:小多
制作人:鑫明
监制:鑫明
出品:金色梦想
古筝:武桐宇
灰色的天冷冷的城
车水马龙吵个不停
伤心的歌难过的梦
破碎的心格外的疼
长长的街暗暗的灯
不见伊人的归程
走过春夏盼过秋冬
多少黄昏哭到黎明
痴痴的爱傻傻的等
等无情人的身影
多情的小雨无情的风
伤心往事不敢触碰
痴痴的爱傻傻的等
彻夜宿醉不愿醒
半弯的月亮坠落的星
岁月匆匆日落日升
长长的街暗暗的灯
不见伊人的归程
走过春夏盼过秋冬
多少黄昏哭到黎明
痴痴的爱傻傻的等
等无情人的身影
多情的小雨无情的风
伤心往事不敢触碰
痴痴的爱傻傻的等
彻夜宿醉不愿醒
半弯的月亮坠落的星
岁月匆匆日落日升
痴痴的爱傻傻的等
彻夜宿醉不愿醒
半弯的月坠落的星
岁月匆匆日落日升
岁月匆匆日落日升
      `;
      state.lyrics = parsePureLRC(pureLRCText);
      const gl = initCheck();
      if (!gl) return;
      window.render = initWebGL(gl);
      bindEvents(gl);
      requestAnimationFrame(window.render.draw);
      updateLyric();
      window.render.updateTextTexture(state.lyrics?.text || '');
      elements.prevLyric.textContent = '';
      elements.currentLyric.textContent = state.lyrics?.text || '';
      elements.nextLyric.textContent = state.lyrics?.text || '';
    }
    window.addEventListener('load', init);


player.addEventListener('click', () => audio.paused ? audio.play() : audio.pause());
let mState = () => audio.paused ? (player.style.setProperty('--sp1','1'), player.style.setProperty('--sp2','0')) : (player.style.setProperty('--sp1','0'), player.style.setProperty('--sp2','1'));
audio.addEventListener('play', () => mState());
audio.addEventListener('pause', () => mState());




</script>

小辣椒 发表于 2025-11-23 15:32

亚纶,我刷新几次看见了,歌词效果漂亮,但加了分后又看不见了,然后再刷新几次又看见了,不知道是不是我的原因,

小辣椒 发表于 2025-11-23 15:33

这个歌词制作我看见别人做过,感觉画面背景要留好歌词出来的位置,效果会更加好,不要遮盖人物最好

杨帆 发表于 2025-11-23 16:06

好听的曲子,新颖的特效,顺畅的效果,谢谢亚伦老师精彩分享{:4_180:}

小辣椒 发表于 2025-11-23 16:17

再进来试一次,这次打开挺快的,小辣椒其实玩的时间太少,亚纶这个我套用会很快的,先收藏代码,感谢亚纶精彩分享

偶然~ 发表于 2025-11-23 16:49

来欣赏亚伦影音工作室精品佳作!

偶然~ 发表于 2025-11-23 16:49

音画太棒了!

偶然~ 发表于 2025-11-23 16:49

音画唯美

偶然~ 发表于 2025-11-23 16:49

背景歌声动听

偶然~ 发表于 2025-11-23 16:49

制作大气

偶然~ 发表于 2025-11-23 16:50

音画合一,音乐与画面结合完美

偶然~ 发表于 2025-11-23 16:50

玫瑰花☆╮╮芍药花☆╮╰☆☆╮合欢花花~【*偶然 献花给你啦】

偶然~ 发表于 2025-11-23 16:50

期待亚伦影音工作室佳作频出!

偶然~ 发表于 2025-11-23 16:50

愿你愿我,每天都是美好。

偶然~ 发表于 2025-11-23 16:50

感谢支持花潮论坛,辛苦了,祝亚伦影音工作室和家人岁岁安康,幸福吉祥!

梦油 发表于 2025-11-23 17:21

欣赏佳作,问候亚伦。

樵歌 发表于 2025-11-23 18:02

赞赏亚伦的特效音画!{:4_199:}

红影 发表于 2025-11-23 21:34

这个特效歌词好奇妙,随意飘荡着,很悠然自在啊{:4_187:}

红影 发表于 2025-11-23 21:35

欣赏亚伦老师精彩特效歌词{:4_199:}

老谟深虑 发表于 2025-11-27 19:22

            制作用心,画面和音乐都很美,喜欢!
页: [1]
查看完整版本: 特效歌词 #多情的小雨无情的风-王思雨#