云端漫步 发表于 2025-8-23 16:11:10

【漫步特效】荷塘月色(分享素材与代码)

本帖最后由 云端漫步 于 2025-9-12 12:27 编辑 <br /><br /><style>
    @import 'https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/tz01.css';
    #pa {
      --offsetX: 0px;
      width: clamp(600px, 120vw, 1700px); /* 适配论坛 */
      height: auto;
      aspect-ratio: 18/9;
      margin: 50px 0 50px calc(50% - 530px); /* 定位方式 */
      top: 130px; /* 一致的顶值 */
      position: relative;
      --bg: url('https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/asa1.jpg') no-repeat center/cover;
      --bg1: url('https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/asa2.jpg') no-repeat center/cover;
      --state: running;
      transition: all 4s cubic-bezier(0.25, 0.1, 0.25, 1);
      --ma-size: 12%;
      --per: 0%;
      --a: 135deg;
      overflow: hidden;
      will-change: transform;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
      z-index: 1; /* 元素覆盖 */
    }
    #pa::before {
      content: '';
      position: absolute;
      inset: 0;
      background: var(--bg1);
      mask: linear-gradient(var(--a),
                            rgba(0,0,0,1) 0%,
                            rgba(0,0,0,0.8) 20%,
                            rgba(0,0,0,0.5) 50%,
                            rgba(0,0,0,0.2) 80%,
                            transparent 100%);
      z-index: 40;
      will-change: mask-position;
      transition: mask-position 0.1s linear;
    }
    .qk-vid {
      mix-blend-mode: screen;
      opacity: .6;
      transition: opacity 4s cubic-bezier(0.25, 0.1, 0.25, 1);
      will-change: opacity;
      position: absolute;
      top: 0;
      left: 0;
      width: 110%;
      height: 110%;
      object-fit: cover;
      transform: translate(-5%, -5%);
      z-index: 50;
    }
   
    .loading-indicator {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 40px;
      height: 40px;
      border: 3px solid rgba(255, 255, 255, 0.3);
      border-radius: 50%;
      border-top-color: white;
      animation: spin 1s ease-in-out infinite;
      z-index: 200;
      display: none;
    }
   
    @keyframes spin {
      to { transform: translate(-50%, -50%) rotate(360deg); }
    }
   
    @keyframes curtainOpenLeft {
      0% { width: 100%; transform: translateX(0); opacity: 1; }
      30% { width: 70%; transform: translateX(-15%); opacity: 1; }
      70% { width: 30%; transform: translateX(-35%); opacity: 0.8; }
      100% { width: 0%; transform: translateX(-100%); opacity: 0; }
    }
   
    @keyframes curtainOpenRight {
      0% { width: 100%; transform: translateX(0); opacity: 1; }
      30% { width: 70%; transform: translateX(15%); opacity: 1; }
      70% { width: 30%; transform: translateX(35%); opacity: 0.8; }
      100% { width: 0%; transform: translateX(100%); opacity: 0; }
    }
   
    .curtain-transition {
      position: absolute;
      height: 100%;
      top: 0;
      background-size: cover;
      background-position: center;
      z-index: 50;
      will-change: width, transform, opacity;
      backface-visibility: hidden;
    }
   
    .curtain-left {
      left: 0;
      animation: curtainOpenLeft 12s forwards cubic-bezier(0.25, 0.1, 0.25, 1);
    }
   
    .curtain-right {
      right: 0;
      animation: curtainOpenRight 12s forwards cubic-bezier(0.25, 0.1, 0.25, 1);
    }
</style>

<div id="pa">
    <div class="loading-indicator"></div>
    <audio id="aud" src="https://ting8.yymp3.com/new18/fhzq4/2.mp3" loop autoplay></audio>
    <video class="qk-vid" src="https://img.tukuppt.com/video_show/2418175/00/02/22/5b52de8ec8111.mp4" autoplay loop muted></video>
</div>

<script type="module">
    var per = 0,
      step = 0.008,
      aniCounter = 0,
      raf,
      baseInterval = 24000,
      interval = baseInterval,
      isPlaying = true,
      isAudioPlaying = true,
      animationTimeout;
   
    var pics = [
      'https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/asa1.jpg',
      'https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/asa2.jpg',
      'https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/asa3.jpg',
      'https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/asa4.jpg',
    ];
   
    // 获取DOM元素
    const loadingIndicator = document.querySelector('.loading-indicator');
    const audioElement = document.getElementById('aud');
    const pa = document.getElementById('pa');
   
    // 音频控制函数
    function toggleAudio() {
      if (audioElement.paused) {
            audioElement.play().then(() => {
                isAudioPlaying = true;
            }).catch(e => {
                console.log('播放失败:', e);
            });
      } else {
            audioElement.pause();
            isAudioPlaying = false;
      }
    }
   
    // 页面交互触发自动播放
    function handleInteraction() {
      if (!isAudioPlaying) {
            audioElement.play().then(() => {
                isAudioPlaying = true;
            }).catch(e => {
                console.log('交互触发播放:', e);
            });
      }
      document.removeEventListener('click', handleInteraction);
      document.removeEventListener('touchstart', handleInteraction);
    }
   
    function preloadImages() {
      loadingIndicator.style.display = 'block';
      let loadedCount = 0;
      
      pics.forEach(src => {
            const img = new Image();
            img.src = src;
            img.onload = img.onerror = () => {
                loadedCount++;
                if (loadedCount === pics.length) {
                  loadingIndicator.style.display = 'none';
                }
            };
      });
    }
   
    let animationStartTime;
    function startAnimationLoop() {
      if (isPlaying) {
            clearTimeout(animationTimeout);
            animationStartTime = Date.now();
            
            animationTimeout = setTimeout(() => {
                changeToNextPic();
            }, interval);
      }
    }
   
    function changeToNextPic() {
      loadingIndicator.style.display = 'block';
      aniCounter = (aniCounter + 1) % pics.length;
      updateCurtainAndBackground(() => {
            loadingIndicator.style.display = 'none';
      });
    }
   
    function updateCurtainAndBackground(callback) {
      const picIdx = aniCounter % pics.length;
      
      document.querySelectorAll('.curtain-transition').forEach(el => el.remove());
      
      const leftCurtain = document.createElement('div');
      leftCurtain.className = 'curtain-transition curtain-left';
      leftCurtain.style.backgroundImage = `url(${pics})`;
      pa.appendChild(leftCurtain);
      
      const rightCurtain = document.createElement('div');
      rightCurtain.className = 'curtain-transition curtain-right';
      rightCurtain.style.backgroundImage = `url(${pics})`;
      pa.appendChild(rightCurtain);
      
      const img = new Image();
      img.src = pics;
      img.onload = img.onerror = callback;
      
      setTimeout(() => {
            pa.style.setProperty('--bg1', `url(${pics}) no-repeat center/cover`);
      }, 2000);
      
      const video = document.querySelector('.qk-vid');
      video.style.opacity = '0.3';
      setTimeout(() => {
            video.style.opacity = '0.6';
      }, 2000);
      
      cancelAnimationFrame(raf);
      per = 0;
      changePic();
      
      if (isPlaying) {
            startAnimationLoop();
      }
    }
   
    function changePic() {
      if (per > 100) {
            per = 0;
      } else if (isPlaying) {
            per += step;
            document.documentElement.style.setProperty('--per', per + '%');
            raf = requestAnimationFrame(changePic);
      }
    }
   
    // 绑定交互事件
    document.addEventListener('click', handleInteraction);
    document.addEventListener('touchstart', handleInteraction);
    document.addEventListener('keydown', (e) => {
      if (e.key.toLowerCase() === 'm') {
            toggleAudio();
            e.preventDefault();
      }
    });
   
    // 初始化
    preloadImages();
    startAnimationLoop();
    changePic();
   
    // 尝试自动播放音乐
    window.addEventListener('load', () => {
      if (audioElement.paused) {
            audioElement.play().then(() => {
                isAudioPlaying = true;
            }).catch(e => {
                console.log('等待用户交互:', e);
            });
      }
    });
</script>
<BR><BR><BR><BR><BR><BR>
</td></tr></table>

云端漫步 发表于 2025-8-23 16:11:38

<style>
    @import 'https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/tz01.css';
    #pa {
      --offsetX: 0px;
      width: clamp(600px, 120vw, 1700px); /* 适配论坛 */
      height: auto;
      aspect-ratio: 18/9;
      margin: 50px 0 50px calc(50% - 530px); /* 定位方式 */
      top: 130px; /* 一致的顶值 */
      position: relative;
      --bg: url('http://kkshan.com/data/attachment/forum/202508/17/234804conly7jan6nnh4oa.jpg') no-repeat center/cover;
      --bg1: url('http://kkshan.com/data/attachment/forum/202508/17/234804conly7jan6nnh4oa.jpg') no-repeat center/cover;
      --state: running;
      transition: all 4s cubic-bezier(0.25, 0.1, 0.25, 1);
      --ma-size: 12%;
      --per: 0%;
      --a: 135deg;
      overflow: hidden;
      will-change: transform;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
      z-index: 1; /* 元素覆盖 */
    }
    #pa::before {
      content: '';
      position: absolute;
      inset: 0;
      background: var(--bg1);
      mask: linear-gradient(var(--a),
                            rgba(0,0,0,1) 0%,
                            rgba(0,0,0,0.8) 20%,
                            rgba(0,0,0,0.5) 50%,
                            rgba(0,0,0,0.2) 80%,
                            transparent 100%);
      z-index: 40;
      will-change: mask-position;
      transition: mask-position 0.1s linear;
    }
    .qk-vid {
      mix-blend-mode: screen;
      opacity: .6;
      transition: opacity 4s cubic-bezier(0.25, 0.1, 0.25, 1);
      will-change: opacity;
      position: absolute;
      top: 0;
      left: 0;
      width: 110%;
      height: 110%;
      object-fit: cover;
      transform: translate(-5%, -5%);
      z-index: 50;
    }
   
    .loading-indicator {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: 40px;
      height: 40px;
      border: 3px solid rgba(255, 255, 255, 0.3);
      border-radius: 50%;
      border-top-color: white;
      animation: spin 1s ease-in-out infinite;
      z-index: 200;
      display: none;
    }
   
    @keyframes spin {
      to { transform: translate(-50%, -50%) rotate(360deg); }
    }
   
    @keyframes curtainOpenLeft {
      0% { width: 100%; transform: translateX(0); opacity: 1; }
      30% { width: 70%; transform: translateX(-15%); opacity: 1; }
      70% { width: 30%; transform: translateX(-35%); opacity: 0.8; }
      100% { width: 0%; transform: translateX(-100%); opacity: 0; }
    }
   
    @keyframes curtainOpenRight {
      0% { width: 100%; transform: translateX(0); opacity: 1; }
      30% { width: 70%; transform: translateX(15%); opacity: 1; }
      70% { width: 30%; transform: translateX(35%); opacity: 0.8; }
      100% { width: 0%; transform: translateX(100%); opacity: 0; }
    }
   
    .curtain-transition {
      position: absolute;
      height: 100%;
      top: 0;
      background-size: cover;
      background-position: center;
      z-index: 50;
      will-change: width, transform, opacity;
      backface-visibility: hidden;
    }
   
    .curtain-left {
      left: 0;
      animation: curtainOpenLeft 12s forwards cubic-bezier(0.25, 0.1, 0.25, 1);
    }
   
    .curtain-right {
      right: 0;
      animation: curtainOpenRight 12s forwards cubic-bezier(0.25, 0.1, 0.25, 1);
    }
</style>

<div id="pa">
    <div class="loading-indicator"></div>
    <audio id="aud" src="https://ting8.yymp3.com/new18/fhzq4/2.mp3" loop autoplay></audio>
    <video class="qk-vid" src="https://img.tukuppt.com/video_show/2418175/00/02/22/5b52de8ec8111.mp4" autoplay loop muted></video>
</div>

<script type="module">
    var per = 0,
      step = 0.008,
      aniCounter = 0,
      raf,
      baseInterval = 24000,
      interval = baseInterval,
      isPlaying = true,
      isAudioPlaying = true,
      animationTimeout;
   
    var pics = [
      'http://kkshan.com/data/attachment/forum/202508/17/234804conly7jan6nnh4oa.jpg',
      'http://kkshan.com/data/attachment/forum/202508/17/234804c87ud86kzjbte86t.jpg',
      'http://kkshan.com/data/attachment/forum/202508/17/234804brayylbaab1km6m6.jpg',
      'http://kkshan.com/data/attachment/forum/202508/17/234805s5pop3gkfereoo5k.jpg',
    ];
   
    // 获取DOM元素
    const loadingIndicator = document.querySelector('.loading-indicator');
    const audioElement = document.getElementById('aud');
    const pa = document.getElementById('pa');
   
    // 音频控制函数
    function toggleAudio() {
      if (audioElement.paused) {
            audioElement.play().then(() => {
                isAudioPlaying = true;
            }).catch(e => {
                console.log('播放失败:', e);
            });
      } else {
            audioElement.pause();
            isAudioPlaying = false;
      }
    }
   
    // 页面交互触发自动播放
    function handleInteraction() {
      if (!isAudioPlaying) {
            audioElement.play().then(() => {
                isAudioPlaying = true;
            }).catch(e => {
                console.log('交互触发播放:', e);
            });
      }
      document.removeEventListener('click', handleInteraction);
      document.removeEventListener('touchstart', handleInteraction);
    }
   
    function preloadImages() {
      loadingIndicator.style.display = 'block';
      let loadedCount = 0;
      
      pics.forEach(src => {
            const img = new Image();
            img.src = src;
            img.onload = img.onerror = () => {
                loadedCount++;
                if (loadedCount === pics.length) {
                  loadingIndicator.style.display = 'none';
                }
            };
      });
    }
   
    let animationStartTime;
    function startAnimationLoop() {
      if (isPlaying) {
            clearTimeout(animationTimeout);
            animationStartTime = Date.now();
            
            animationTimeout = setTimeout(() => {
                changeToNextPic();
            }, interval);
      }
    }
   
    function changeToNextPic() {
      loadingIndicator.style.display = 'block';
      aniCounter = (aniCounter + 1) % pics.length;
      updateCurtainAndBackground(() => {
            loadingIndicator.style.display = 'none';
      });
    }
   
    function updateCurtainAndBackground(callback) {
      const picIdx = aniCounter % pics.length;
      
      document.querySelectorAll('.curtain-transition').forEach(el => el.remove());
      
      const leftCurtain = document.createElement('div');
      leftCurtain.className = 'curtain-transition curtain-left';
      leftCurtain.style.backgroundImage = `url(${pics})`;
      pa.appendChild(leftCurtain);
      
      const rightCurtain = document.createElement('div');
      rightCurtain.className = 'curtain-transition curtain-right';
      rightCurtain.style.backgroundImage = `url(${pics})`;
      pa.appendChild(rightCurtain);
      
      const img = new Image();
      img.src = pics;
      img.onload = img.onerror = callback;
      
      setTimeout(() => {
            pa.style.setProperty('--bg1', `url(${pics}) no-repeat center/cover`);
      }, 2000);
      
      const video = document.querySelector('.qk-vid');
      video.style.opacity = '0.3';
      setTimeout(() => {
            video.style.opacity = '0.6';
      }, 2000);
      
      cancelAnimationFrame(raf);
      per = 0;
      changePic();
      
      if (isPlaying) {
            startAnimationLoop();
      }
    }
   
    function changePic() {
      if (per > 100) {
            per = 0;
      } else if (isPlaying) {
            per += step;
            document.documentElement.style.setProperty('--per', per + '%');
            raf = requestAnimationFrame(changePic);
      }
    }
   
    // 绑定交互事件
    document.addEventListener('click', handleInteraction);
    document.addEventListener('touchstart', handleInteraction);
    document.addEventListener('keydown', (e) => {
      if (e.key.toLowerCase() === 'm') {
            toggleAudio();
            e.preventDefault();
      }
    });
   
    // 初始化
    preloadImages();
    startAnimationLoop();
    changePic();
   
    // 尝试自动播放音乐
    window.addEventListener('load', () => {
      if (audioElement.paused) {
            audioElement.play().then(() => {
                isAudioPlaying = true;
            }).catch(e => {
                console.log('等待用户交互:', e);
            });
      }
    });
</script>
<BR><BR><BR><BR><BR><BR>

云端漫步 发表于 2025-8-23 16:13:07

分享素材

欧阳风刀 发表于 2025-8-23 18:07:09

{:7_182:}特效制作精彩,画面美不胜收!狠狠赞赞!

欧阳风刀 发表于 2025-8-23 18:07:49

感谢哥们代码及素材的分享!周末愉快啊!{:7_196:}

云中白鹤 发表于 2025-8-23 22:30:44

漂亮,支持一下

圊圊淥詶 发表于 2025-8-24 10:02:19

好看的特效,完美~~
做的很漂亮{:1_150:}

圊圊淥詶 发表于 2025-8-24 10:03:22

谢谢漫步老师,辛苦了哦,
还分享了代码,漫步老师有心了,有空学一下;P

圊圊淥詶 发表于 2025-8-24 10:03:41

谢谢漫步老师的分享,遥祝周末快乐~~{:1_153:}

玫の玫 发表于 2025-8-24 14:49:14

欣赏漫步老师精美制作!
页: [1] 2
查看完整版本: 【漫步特效】荷塘月色(分享素材与代码)