设为首页收藏本站

云荷-个人作品展示

 找回密码
 中文注册

QQ登录

只需一步,快速开始

搜索
热搜: 音画 图文 音乐
查看: 59|回复: 16
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
楼主
发表于 昨天 16:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式






评分

5

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

沙发
 楼主| 发表于 昨天 16:11 | 只看该作者
  1. <style>
  2.     @import 'https://webftp-bbs.hnol.net/ggkj2017/yunduanmanbu/16/6/2/tz01.css';
  3.     #pa {
  4.         --offsetX: 0px;
  5.         width: clamp(600px, 120vw, 1700px); /* 适配论坛 */
  6.         height: auto;
  7.         aspect-ratio: 18/9;
  8.         margin: 50px 0 50px calc(50% - 530px); /* 定位方式 */
  9.         top: 130px; /* 一致的顶值 */
  10.         position: relative;
  11.         --bg: url('http://kkshan.com/data/attachment/forum/202508/17/234804conly7jan6nnh4oa.jpg') no-repeat center/cover;
  12.         --bg1: url('http://kkshan.com/data/attachment/forum/202508/17/234804conly7jan6nnh4oa.jpg') no-repeat center/cover;
  13.         --state: running;
  14.         transition: all 4s cubic-bezier(0.25, 0.1, 0.25, 1);
  15.         --ma-size: 12%;
  16.         --per: 0%;
  17.         --a: 135deg;
  18.         overflow: hidden;
  19.         will-change: transform;
  20.         box-shadow: 0 10px 30px rgba(0,0,0,0.2);
  21.         z-index: 1; /* 元素覆盖 */
  22.     }
  23.     #pa::before {
  24.         content: '';
  25.         position: absolute;
  26.         inset: 0;
  27.         background: var(--bg1);
  28.         mask: linear-gradient(var(--a),
  29.                             rgba(0,0,0,1) 0%,
  30.                             rgba(0,0,0,0.8) 20%,
  31.                             rgba(0,0,0,0.5) 50%,
  32.                             rgba(0,0,0,0.2) 80%,
  33.                             transparent 100%);
  34.         z-index: 40;
  35.         will-change: mask-position;
  36.         transition: mask-position 0.1s linear;
  37.     }
  38.     .qk-vid {
  39.         mix-blend-mode: screen;
  40.         opacity: .6;
  41.         transition: opacity 4s cubic-bezier(0.25, 0.1, 0.25, 1);
  42.         will-change: opacity;
  43.         position: absolute;
  44.         top: 0;
  45.         left: 0;
  46.         width: 110%;
  47.         height: 110%;
  48.         object-fit: cover;
  49.         transform: translate(-5%, -5%);
  50.         z-index: 50;
  51.     }
  52.    
  53.     .loading-indicator {
  54.         position: absolute;
  55.         top: 50%;
  56.         left: 50%;
  57.         transform: translate(-50%, -50%);
  58.         width: 40px;
  59.         height: 40px;
  60.         border: 3px solid rgba(255, 255, 255, 0.3);
  61.         border-radius: 50%;
  62.         border-top-color: white;
  63.         animation: spin 1s ease-in-out infinite;
  64.         z-index: 200;
  65.         display: none;
  66.     }
  67.    
  68.     @keyframes spin {
  69.         to { transform: translate(-50%, -50%) rotate(360deg); }
  70.     }
  71.    
  72.     @keyframes curtainOpenLeft {
  73.         0% { width: 100%; transform: translateX(0); opacity: 1; }
  74.         30% { width: 70%; transform: translateX(-15%); opacity: 1; }
  75.         70% { width: 30%; transform: translateX(-35%); opacity: 0.8; }
  76.         100% { width: 0%; transform: translateX(-100%); opacity: 0; }
  77.     }
  78.    
  79.     @keyframes curtainOpenRight {
  80.         0% { width: 100%; transform: translateX(0); opacity: 1; }
  81.         30% { width: 70%; transform: translateX(15%); opacity: 1; }
  82.         70% { width: 30%; transform: translateX(35%); opacity: 0.8; }
  83.         100% { width: 0%; transform: translateX(100%); opacity: 0; }
  84.     }
  85.    
  86.     .curtain-transition {
  87.         position: absolute;
  88.         height: 100%;
  89.         top: 0;
  90.         background-size: cover;
  91.         background-position: center;
  92.         z-index: 50;
  93.         will-change: width, transform, opacity;
  94.         backface-visibility: hidden;
  95.     }
  96.    
  97.     .curtain-left {
  98.         left: 0;
  99.         animation: curtainOpenLeft 12s forwards cubic-bezier(0.25, 0.1, 0.25, 1);
  100.     }
  101.    
  102.     .curtain-right {
  103.         right: 0;
  104.         animation: curtainOpenRight 12s forwards cubic-bezier(0.25, 0.1, 0.25, 1);
  105.     }
  106. </style>

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

  112. <script type="module">
  113.     var per = 0,
  114.         step = 0.008,
  115.         aniCounter = 0,
  116.         raf,
  117.         baseInterval = 24000,
  118.         interval = baseInterval,
  119.         isPlaying = true,
  120.         isAudioPlaying = true,
  121.         animationTimeout;
  122.    
  123.     var pics = [
  124.         'http://kkshan.com/data/attachment/forum/202508/17/234804conly7jan6nnh4oa.jpg',
  125.         'http://kkshan.com/data/attachment/forum/202508/17/234804c87ud86kzjbte86t.jpg',
  126.         'http://kkshan.com/data/attachment/forum/202508/17/234804brayylbaab1km6m6.jpg',
  127.         'http://kkshan.com/data/attachment/forum/202508/17/234805s5pop3gkfereoo5k.jpg',
  128.     ];
  129.    
  130.     // 获取DOM元素
  131.     const loadingIndicator = document.querySelector('.loading-indicator');
  132.     const audioElement = document.getElementById('aud');
  133.     const pa = document.getElementById('pa');
  134.    
  135.     // 音频控制函数
  136.     function toggleAudio() {
  137.         if (audioElement.paused) {
  138.             audioElement.play().then(() => {
  139.                 isAudioPlaying = true;
  140.             }).catch(e => {
  141.                 console.log('播放失败:', e);
  142.             });
  143.         } else {
  144.             audioElement.pause();
  145.             isAudioPlaying = false;
  146.         }
  147.     }
  148.    
  149.     // 页面交互触发自动播放
  150.     function handleInteraction() {
  151.         if (!isAudioPlaying) {
  152.             audioElement.play().then(() => {
  153.                 isAudioPlaying = true;
  154.             }).catch(e => {
  155.                 console.log('交互触发播放:', e);
  156.             });
  157.         }
  158.         document.removeEventListener('click', handleInteraction);
  159.         document.removeEventListener('touchstart', handleInteraction);
  160.     }
  161.    
  162.     function preloadImages() {
  163.         loadingIndicator.style.display = 'block';
  164.         let loadedCount = 0;
  165.         
  166.         pics.forEach(src => {
  167.             const img = new Image();
  168.             img.src = src;
  169.             img.onload = img.onerror = () => {
  170.                 loadedCount++;
  171.                 if (loadedCount === pics.length) {
  172.                     loadingIndicator.style.display = 'none';
  173.                 }
  174.             };
  175.         });
  176.     }
  177.    
  178.     let animationStartTime;
  179.     function startAnimationLoop() {
  180.         if (isPlaying) {
  181.             clearTimeout(animationTimeout);
  182.             animationStartTime = Date.now();
  183.             
  184.             animationTimeout = setTimeout(() => {
  185.                 changeToNextPic();
  186.             }, interval);
  187.         }
  188.     }
  189.    
  190.     function changeToNextPic() {
  191.         loadingIndicator.style.display = 'block';
  192.         aniCounter = (aniCounter + 1) % pics.length;
  193.         updateCurtainAndBackground(() => {
  194.             loadingIndicator.style.display = 'none';
  195.         });
  196.     }
  197.    
  198.     function updateCurtainAndBackground(callback) {
  199.         const picIdx = aniCounter % pics.length;
  200.         
  201.         document.querySelectorAll('.curtain-transition').forEach(el => el.remove());
  202.         
  203.         const leftCurtain = document.createElement('div');
  204.         leftCurtain.className = 'curtain-transition curtain-left';
  205.         leftCurtain.style.backgroundImage = `url(${pics[picIdx]})`;
  206.         pa.appendChild(leftCurtain);
  207.         
  208.         const rightCurtain = document.createElement('div');
  209.         rightCurtain.className = 'curtain-transition curtain-right';
  210.         rightCurtain.style.backgroundImage = `url(${pics[picIdx]})`;
  211.         pa.appendChild(rightCurtain);
  212.         
  213.         const img = new Image();
  214.         img.src = pics[picIdx];
  215.         img.onload = img.onerror = callback;
  216.         
  217.         setTimeout(() => {
  218.             pa.style.setProperty('--bg1', `url(${pics[picIdx]}) no-repeat center/cover`);
  219.         }, 2000);
  220.         
  221.         const video = document.querySelector('.qk-vid');
  222.         video.style.opacity = '0.3';
  223.         setTimeout(() => {
  224.             video.style.opacity = '0.6';
  225.         }, 2000);
  226.         
  227.         cancelAnimationFrame(raf);
  228.         per = 0;
  229.         changePic();
  230.         
  231.         if (isPlaying) {
  232.             startAnimationLoop();
  233.         }
  234.     }
  235.    
  236.     function changePic() {
  237.         if (per > 100) {
  238.             per = 0;
  239.         } else if (isPlaying) {
  240.             per += step;
  241.             document.documentElement.style.setProperty('--per', per + '%');
  242.             raf = requestAnimationFrame(changePic);
  243.         }
  244.     }
  245.    
  246.     // 绑定交互事件
  247.     document.addEventListener('click', handleInteraction);
  248.     document.addEventListener('touchstart', handleInteraction);
  249.     document.addEventListener('keydown', (e) => {
  250.         if (e.key.toLowerCase() === 'm') {
  251.             toggleAudio();
  252.             e.preventDefault();
  253.         }
  254.     });
  255.    
  256.     // 初始化
  257.     preloadImages();
  258.     startAnimationLoop();
  259.     changePic();
  260.    
  261.     // 尝试自动播放音乐
  262.     window.addEventListener('load', () => {
  263.         if (audioElement.paused) {
  264.             audioElement.play().then(() => {
  265.                 isAudioPlaying = true;
  266.             }).catch(e => {
  267.                 console.log('等待用户交互:', e);
  268.             });
  269.         }
  270.     });
  271. </script>
  272. <BR><BR><BR><BR><BR><BR>
复制代码

评分

3

查看全部评分

回复 支持 反对

使用道具 举报

板凳
 楼主| 发表于 昨天 16:13 | 只看该作者
分享素材

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?中文注册

x

评分

2

查看全部评分

回复

使用道具 举报

地板
发表于 昨天 18:07 | 只看该作者
特效制作精彩,画面美不胜收!狠狠赞赞!
回复 支持 反对

使用道具 举报

5#
发表于 昨天 18:07 | 只看该作者
感谢哥们代码及素材的分享!周末愉快啊!
回复 支持 反对

使用道具 举报

6#
发表于 昨天 22:30 | 只看该作者
漂亮,支持一下
回复 支持 反对

使用道具 举报

7#
发表于 5 小时前 | 只看该作者
好看的特效,完美~~
做的很漂亮
回复 支持 反对

使用道具 举报

8#
发表于 5 小时前 | 只看该作者
谢谢漫步老师,辛苦了哦,
还分享了代码,漫步老师有心了,有空学一下
回复 支持 反对

使用道具 举报

9#
发表于 5 小时前 | 只看该作者
谢谢漫步老师的分享,遥祝周末快乐~~
回复 支持 反对

使用道具 举报

10#
发表于 14 分钟前 | 只看该作者
欣赏漫步老师精美制作!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 中文注册

本版积分规则

苏ICP备16043306号-1    

GMT+8, 2025-8-24 15:03 , Processed in 0.221511 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表