杨帆 发表于 2026-7-16 21:43

太阳出来照四方

本帖最后由 杨帆 于 2026-7-17 13:12 编辑 <br /><br /><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="referrer" content="never"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="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" rel="stylesheet">
<title>罗姣 - 太阳出来照四方</title>
<style>
@import 'https://638183.freep.cn/638183/web/api/audioplayer.css';
.pa { position: relative; --offsetX: 81px; --state: running; --bg:#000 url('https://cccimg.com/view.php/f3aec8e46568ef105ec71e26c5c72564.jpg') no-repeat center/cover; color: lightblue; width: 1280px; height: 750px; overflow: hidden; z-index: 1; color:Aqua; }
.player { width: 480px; bottom: 10px; }
.btnFs { top: 25px; right: 20px; }
#vid { position: absolute; left: -10%; top: -10%; width: 120%; height:120%; object-fit: cover; pointer-events: none; z-index: -1;mask: linear-gradient(to bottom, red 0% ,transparent 71%,transparent);-webkit-mask: linear-gradient(to bottom, red 0% ,transparent 71%,transparent); opacity: 0.98; }
.li-zi { position: absolute; width: 60px; height: 60px; background: url('https://638183.freep.cn/638183/t23/btn/y5j.png') no-repeat center/cover; offset-path: path('M0,200 Q390,-180 1800,200'); animation: move 10s linear infinite var(--state); }
@keyframes move { to { offset-distance: 100%; } }
#msvg { position: absolute; z-index: 20; left: 45px; top: 45px; width: 120px; height: 120px; display: block; }
#cpath { cursor: pointer; filter: drop-shadow(0 0 4px #000); transform-origin: 50%; animation: rot 6s linear infinite var(--state), chgcolor 12s linear infinite alternate var(--state); }
@keyframes rot { to { transform: rotate(360deg); stroke-dashoffset: -160; } }
@keyframes chgcolor { to { fill: rgba(100,55,30,.1); } }
#lyricBox { width: 100%; height: 100%; position: absolute; top: -120PX; left: 0; z-index: 10; pointer-events: none; }
.char-particle { position: absolute; letter-spacing: 8px !important; font-weight: bold; font-family: 'Long Cang','ZCOOL KuaiLe','Ma Shan Zheng', '华文琥珀', STLiti,cursive; will-change: transform, opacity, color; transition: none; font-size: 58px !important; }
.lizi { position: absolute; width: 80px; height: 2px; border-radius: 100% 20%;background: tan;z-index: 2;}
</style>
</head>
<body>
<div class="pa">
<video id = "vid" src="https://video-qn.51miz.com/vcg/video/preview/51miz42N1337588768.mp4" autoplay loop preload="auto" playsinline muted></video>
<div id="lyricBox"></div>
<svg id="msvg" width="200" height="200"viewBox="0 0 200 200"><title id = "svgTip">暂停</title>
<defs>
<g id="cpath"fill="rgba(210,105,30,.15)" stroke="rgba(255,255,255,.8)" stroke-width="4" stroke-dasharray="4">
<path d='M100 120 C10 -30,190 -30,100 120'/>
</g>
</defs>
</svg>
<div class="player"></div>
</div>
<script>
const PARTICLE_CONFIG = {
    minLineWidth: 880,
    charSpreadBase: 220,
    charSpreadRange: 6,
    charDurationMin: 1300,
    charDurationMax: 1700,
    charDelayMax: 120,
    charScaleMin: 1,
    charRotateMin: -2,
    charRotateMax: 2,
    fadeOutDuration: 350
};
const COLORS = ['#b896ff','#9b7bff','#7a5cbf','#a67cff','#d4b8ff','#6d4c9a','#8f6fd9','#c9aaff','#b09aff','#7f5fc4','#e0c8ff','#9f80e6'];
let LYRICS = [];
let currentParticles = [];
let isTransitioning = false;
let animFrameId = null;
let colorLoopId = null;
let lyricThrottleTimer = null;
let pendingLyricIndex = null;
let audioIsPaused = true;
let currentIndex = 0;
let audioElement = null;
function parseLRC(lrc) {
    const lines = lrc.split('\n');
    const result = [];
    const reg = /\[(\d{2}):(\d{2})\.(\d+)\]/;
    for (const line of lines) {
      const trimmed = line.trim();
      if (!trimmed) continue;
      const match = trimmed.match(reg);
      if (match) {
            const min = +match, sec = +match, ms = +match;
            const time = min * 60 + sec + ms / 1000;
            const text = trimmed.replace(/\[.*?\]/g, '').trim();
            text && result.push({ time, text });
      }
    }
    result.sort((a, b) => a.time - b.time);
    return result;
}
const gc = `太阳出来照四方
演唱:罗姣
太阳出来照四方
毛主席的思想閃金光
太阳照的人身暖哎
毛主席思想的光辉
照得咱心里亮
照得咱心里亮
主席的思想传四方
革命的人民有了主张
男女老少齐参战咧
人民战争就是那无敌的力量
是无敌的力量
主席的话儿记心上
哪怕敌人逞凶狂
咱们摆下了天罗地网哎
要把那些强盗豺狼
全都埋葬 全都埋葬
把它们全埋葬
`;
const LRC_STRING = gc;
LYRICS = parseLRC(LRC_STRING);
function getRandomColor() {
    return COLORS;
}
function getTargetPosition(idx, total, centerX, fixedY) {
    const singleCharW = 55;
    let totalW = total * singleCharW;
    if (totalW > PARTICLE_CONFIG.maxLineWidth) totalW = PARTICLE_CONFIG.maxLineWidth;
    const singleWidth = totalW / total;
    const offsetX = idx * singleWidth - totalW / 2;
    const tinyXJitter = (Math.random() - 0.5) * PARTICLE_CONFIG.charSpreadRange;
    return {
      x: centerX + offsetX + tinyXJitter,
      y: fixedY
    };
}
function createLyricParticles(text, fixedHorizontalY) {
    const box = document.getElementById('lyricBox');
    const boxCenterX = box.clientWidth / 2;
    const charList = text.split('');
    const totalCharNum = charList.length;
    const particleArr = [];
    const fontSize = 52;
    for (let i = 0; i < totalCharNum; i++) {
      const char = charList;
      const isBlank = char === ' ' || char === '\u3000';
      const targetPos = getTargetPosition(i, totalCharNum, boxCenterX, fixedHorizontalY);
      const animDur = PARTICLE_CONFIG.charDurationMin + Math.random() * (PARTICLE_CONFIG.charDurationMax - PARTICLE_CONFIG.charDurationMin);
      const delayVal = Math.random() * PARTICLE_CONFIG.charDelayMax;
      const rotateVal = PARTICLE_CONFIG.charRotateMin + Math.random() * (PARTICLE_CONFIG.charRotateMax - PARTICLE_CONFIG.charRotateMin);
      const huePhase = Math.random() * Math.PI * 2;
      const span = document.createElement('span');
      span.className = 'char-particle';
      span.textContent = isBlank ? '\u00A0' : char;
      if (isBlank) span.style.opacity = '0';
      span.style.color = getRandomColor();
      span.style.fontSize = fontSize + 'px';
      span.style.left = boxCenterX + 'px';
      span.style.top = fixedHorizontalY + 'px';
      span.style.transform = 'translate(-50%, -50%) scale(0.2) rotate(0deg)';
      span.style.opacity = '0';
      span.style.textShadow = '1px 1px 0 #1a0a2e,2px 2px 0 #1a0a2e,3px 0 rgba(26,10,46,0.8),4px 4px 0 rgba(26,10,46,0.6)';
      span.dataset.phase = huePhase;
      box.appendChild(span);
      particleArr.push({
            el: span,
            char: char,
            isSpace: isBlank,
            startX: boxCenterX,
            startY: fixedHorizontalY,
            targetX: targetPos.x,
            targetY: fixedHorizontalY,
            targetScale: PARTICLE_CONFIG.charScaleMin,
            targetRotation: rotateVal,
            duration: animDur,
            delay: delayVal,
            startTime: null,
            finished: false,
            fadingOut: false,
            phase: huePhase
      });
    }
    return particleArr;
}
function animateLyricParticles(particleList, animStartStamp, finishCallback) {
    let animStarted = false;
    function renderStep(timeStamp) {
      if (!animStarted) {
            animStarted = true;
            particleList.forEach(p => p.startTime = timeStamp + p.delay);
      }
      let allCharsFinish = true;
      for (const p of particleList) {
            if (p.isSpace || p.fadingOut) continue;
            const timePassed = timeStamp - p.startTime;
            const progress = Math.min(timePassed / p.duration, 1);
            const smoothEase = 1 - Math.pow(1 - progress, 3);
            const moveX = p.startX + (p.targetX - p.startX) * smoothEase;
            const scale = 0.2 + (p.targetScale - 0.2) * smoothEase;
            const rotate = p.targetRotation * smoothEase;
            const opacity = progress < 0.1 ? progress / 0.1 : 1;
            p.el.style.left = moveX + 'px';
            p.el.style.top = p.targetY + 'px';
            p.el.style.transform = `translate(-50%, -50%) scale(${scale}) rotate(${rotate}deg)`;
            p.el.style.opacity = opacity;
            if (progress >= 1) {
                p.finished = true;
                p.el.style.left = p.targetX + 'px';
                p.el.style.top = p.targetY + 'px';
                p.el.style.transform = `translate(-50%, -50%) scale(${p.targetScale}) rotate(${p.targetRotation}deg)`;
                p.el.style.opacity = '1';
            } else {
                allCharsFinish = false;
            }
      }
      if (allCharsFinish) {
            finishCallback?.();
            return;
      }
      animFrameId = requestAnimationFrame(renderStep);
    }
    animFrameId = requestAnimationFrame(renderStep);
}
function fadeOutParticles(particleList, fadeTime, callback) {
    const start = performance.now();
    function step(now) {
      const progress = Math.min((now - start) / fadeTime, 1);
      const ease = 1 - Math.pow(1 - progress, 2);
      for (const p of particleList) {
            if (p.isSpace) continue;
            p.fadingOut = true;
            const alpha = 1 - ease;
            const scale = p.targetScale * (1 - ease * 0.7);
            p.el.style.opacity = alpha;
            p.el.style.transform = `translate(-50%, -50%) scale(${scale}) rotate(${p.targetRotation}deg)`;
      }
      if (progress >= 1) {
            particleList.forEach(p => p.el.parentNode?.removeChild(p.el));
            currentParticles = [];
            callback?.();
            return;
      }
      requestAnimationFrame(step);
    }
    requestAnimationFrame(step);
}
function showLyric(index, callback) {
    if (index < 0 || index >= LYRICS.length) return;
    if (index === currentIndex) return;
    if (isTransitioning) {
      if (pendingLyricIndex !== index) {
            pendingLyricIndex = index;
      }
      return;
    }
    pendingLyricIndex = null;
    isTransitioning = true;
    const box = document.getElementById('lyricBox');
    const boxRect = box.getBoundingClientRect();
    const fixedY = boxRect.height - 70;
    if (currentParticles.length > 0) {
      fadeOutParticles([...currentParticles], PARTICLE_CONFIG.fadeOutDuration, () => {
            createAndRender(index, fixedY, callback);
      });
    } else {
      createAndRender(index, fixedY, callback);
    }
}
function createAndRender(index, fixedY, callback) {
    const lyricLine = LYRICS;
    const newParticles = createLyricParticles(lyricLine.text, fixedY);
    currentParticles = newParticles;
    animateLyricParticles(newParticles, performance.now(), () => {
      isTransitioning = false;
      if (pendingLyricIndex !== null) {
            showLyric(pendingLyricIndex);
      }
      callback?.();
    });
    currentIndex = index;
}
function startColorLoop() {
    colorLoopId && cancelAnimationFrame(colorLoopId);
    let baseTime = performance.now();
    function updateColor(timeStamp) {
      const sec = (timeStamp - baseTime) / 1000;
      for (const p of currentParticles) {
            if (p.isSpace || !p.el.parentNode) continue;
            const hue = (sec * 30 + p.phase * 180 / Math.PI) % 360;
            const color = `hsl(${hue}, 100%, 45%)`;
            p.el.style.color = color;
            p.el.style.textShadow = `1px 1px 0 #1a0a2e,2px 2px 0 #1a0a2e,3px 0 rgba(26,10,46,0.8),4px 4px 0 rgba(26,10,46,0.6),0 0 20px ${color},0 0 60px ${color},0 0 100px ${color}`;
      }
      colorLoopId = requestAnimationFrame(updateColor);
    }
    colorLoopId = requestAnimationFrame(updateColor);
}
function syncLyric() {
    if (!audioElement || audioIsPaused) return;
    if (lyricThrottleTimer) return;
    lyricThrottleTimer = setTimeout(() => {
      const curTime = audioElement.currentTime;
      let targetIdx = 0;
      for (let i = 0; i < LYRICS.length; i++) {
            if (LYRICS.time <= curTime) {
                targetIdx = i;
            }
      }
      if (targetIdx !== currentIndex) {
            showLyric(targetIdx);
      }
      lyricThrottleTimer = null;
    }, 200);
}
const options = {
    pa: '.pa',
    urls: [
      ['https://www.joy127.com/url/155573.mp3', '罗姣 - 太阳出来照四方']
    ]
};
const pa = document.querySelector('.pa');
const vid = document.getElementById('vid');

function loadJs(url, callback) {
    const script = document.createElement('script');
    script.charset = 'utf-8';
    script.src = url;
    script.onload = function () {
      if (callback) callback();
    };
    document.head.appendChild(script);
}
loadJs('https://638183.freep.cn/638183/web/api/audioplayer.min.js', tzRun);

['contextmenu', 'dragstart', 'selectstart'].forEach(function (ev) {
    pa.addEventListener(ev, function (e) {
      e.preventDefault();
    });
});
function tzRun() {
    const aud = new AudPlayer(options);
    audioElement = aud.aud;
    audioElement.ontimeupdate = syncLyric;
    audioElement.addEventListener('play', () => {
      audioIsPaused = false;
      startColorLoop();
      syncLyric();
    });
    audioElement.addEventListener('pause', () => {
      audioIsPaused = true;
      cancelAnimationFrame(colorLoopId);
    });
    startColorLoop();
    const msvg = document.getElementById('msvg');
    const tip = document.getElementById('svgTip');   
    msvg.onclick = function () {
      document.querySelectorAll('.lizi').forEach(el => {
            el.getAnimations().forEach(anim => {
                audioElement.paused ? anim.play() : anim.pause();
            });
      });
      if (audioElement.paused) {
            audioElement.play().catch(() => {});
            vid.play();
      } else {
            audioElement.pause();
            vid.pause();
      }
      tip.textContent = audioElement.paused ? '播放' : '暂停';
      pa.style.setProperty('--state', audioElement.paused ? 'paused' : 'running');
    };   
    audioElement.play().catch(err=>console.log("自动播放被浏览器拦截:",err));
    vid.play().catch(()=>{});
}
function mkLeaves(total) {
    let str = '';
    Array(total).fill().forEach((_, idx) => {
      str += `<use href="#cpath" transform="rotate(${360 / total * idx} 100 100)"/>`;
    });
    return str;
}
const msvg = document.getElementById('msvg');
msvg.innerHTML += mkLeaves(5);
const papa = document.querySelector('.pa');
function clearAllParticles() {
   papa.querySelectorAll('.li-zi').forEach(item => item.remove());
}
Array.from({ length: 20 }).forEach(() => {
    const size = 30 + Math.floor(Math.random() * 30);
    const star = document.createElement('div');
    star.className = 'li-zi';
    star.style.cssText += `left: 0; top: ${Math.random() * 140 + 60}px; width: ${size}px; height: ${size}px; opacity: ${Math.random() * 0.4 + 0.4}; animation-delay: -${Math.random() * 10}s;`;
    papa.prepend(star);
});
document.addEventListener('visibilitychange', () => {
    if (document.hidden) {
      if (!audioElement.paused) audioElement.pause();
      audioIsPaused = true;
      cancelAnimationFrame(animFrameId);
      cancelAnimationFrame(colorLoopId);
    } else {
      if (audioElement.paused && !audioElement.ended) {
            audioElement.play().catch(() => {});
            audioIsPaused = false;
            startColorLoop();
      }
    }
});
window.addEventListener('resize', () => {
    if (currentParticles.length > 0) {
      fadeOutParticles([...currentParticles], PARTICLE_CONFIG.fadeOutDuration, () => {
            showLyric(currentIndex);
      });
    }
});
window.addEventListener('beforeunload', () => {
    cancelAnimationFrame(animFrameId);
    cancelAnimationFrame(colorLoopId);
    clearTimeout(lyricThrottleTimer);
    if (currentParticles.length) fadeOutParticles([...currentParticles], 0, () => {});
});
(function() {
let all = 200;
document.querySelectorAll('.lizi').forEach(item => item.remove());
const innerRadius = 250;
const outerRadiusX = 900;
const outerRadiusY = 700;
for (let i = 0; i < all; i++) {
    let movBall = document.createElement('div');
    movBall.className = 'lizi';
    let hudu = (Math.PI / 180) * (360 / all) * i;
    let endX = outerRadiusX * Math.cos(hudu);
    let endY = outerRadiusY * Math.sin(hudu);
    let startX = innerRadius * Math.cos(hudu);
    let startY = innerRadius * Math.sin(hudu);
    if (Math.hypot(endX, endY) <= innerRadius) continue;
    const deg = (360 / all) * i;
    const duration = Math.random() * 3 + 2;
    const delay = -Math.random() * 3;
    movBall.style.cssText += `
      --deg: ${deg}deg;
      background: #${Math.random().toString(16).substr(-6).padStart(6, '0')};
    `;
    movBall.animate(
      [
      {
          transform: `translate(${startX}px, ${startY}px) rotate(${deg}deg)`,
          opacity: 0,
      },
      {
          transform: `translate(${endX}px, ${endY}px) rotate(${deg}deg)`,
          opacity: 1,
          filter: 'hue-rotate(360deg)',
      },
      ],
      {
      duration: duration * 1000,
      delay: delay * 1000,
      iterations: Infinity,
      easing: 'linear',
      }
    );
    papa.prepend(movBall);
}
})();
</script>
</body>
</html>

偶然~ 发表于 2026-7-16 21:47

来欣赏杨帆老师的精品佳作!

偶然~ 发表于 2026-7-16 21:47

音画太棒了!

偶然~ 发表于 2026-7-16 21:47

音画唯美

偶然~ 发表于 2026-7-16 21:47

《太阳出来照四方》歌声动听

偶然~ 发表于 2026-7-16 21:47

制作大气磅礴

偶然~ 发表于 2026-7-16 21:47

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

偶然~ 发表于 2026-7-16 21:48

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

偶然~ 发表于 2026-7-16 21:48

期待杨帆老师佳作频出!

偶然~ 发表于 2026-7-16 21:48

感谢杨帆老师带来的精彩,辛苦了!祝你开心幸福、阖家安康!

红影 发表于 2026-7-16 21:56

歌曲好听,制作很好看,好听的红歌。
欣赏杨帆好帖{:4_199:}

霜染枫丹 发表于 2026-7-16 23:32

刻在记忆中的歌曲,听着就特别亲切!赞佩佳作,晚上好~~{:4_204:}{:4_190:}

梦江南 发表于 2026-7-17 07:27

经典永恒,画面雄伟,制作精美。欣赏问好!{:4_187:}

梦油 发表于 2026-7-17 10:44

红歌是永恒的经典,它见证了中华民族的崛起与发展,唱出了一代又一代中华儿女的豪情壮志。我喜欢!

红影 发表于 2026-7-17 10:53

奇怪,第二句歌词为什么显示“毛主席的思想铩金光”,去帖子里看,明明是闪字啊{:4_203:}

杨帆 发表于 2026-7-17 13:13

偶然~ 发表于 2026-7-16 21:47
来欣赏杨帆老师的精品佳作!

问好偶然~,谢谢兄弟鼓励,祝夏安{:4_190:}

杨帆 发表于 2026-7-17 13:18

霜染枫丹 发表于 2026-7-16 23:32
刻在记忆中的歌曲,听着就特别亲切!赞佩佳作,晚上好~~

是,听起来很温暖,让人心潮澎湃,斗志昂扬,直抵心扉{:4_204:}

杨帆 发表于 2026-7-17 13:19

梦江南 发表于 2026-7-17 07:27
经典永恒,画面雄伟,制作精美。欣赏问好!

是,让人震撼的歌曲,谢谢江南鼓励,祝夏安{:4_204:}

杨帆 发表于 2026-7-17 13:23

梦油 发表于 2026-7-17 10:44
红歌是永恒的经典,它见证了中华民族的崛起与发展,唱出了一代又一代中华儿女的豪情壮志。我喜欢!

持久的经典魅力,总让人焕发出新的生命活力,谢谢梦兄喜欢与鼓励,祝夏安{:4_190:}

杨帆 发表于 2026-7-17 13:28

红影 发表于 2026-7-17 10:53
奇怪,第二句歌词为什么显示“毛主席的思想铩金光”,去帖子里看,明明是闪字啊

似乎是在线字体库的问题,换成闪的繁体字:閃,可以正常显示,谢谢影子{:4_204:}
页: [1] 2
查看完整版本: 太阳出来照四方