查看: 527|回复: 53

[同图] 【漫步特效】荷塘月色(欢迎同图)(分享素材与代码)

[复制链接]
发表于 2025-8-22 16:15 | 显示全部楼层 |阅读模式
本帖最后由 云端漫步 于 2025-9-12 05:06 编辑







评分

11

查看全部评分

点评
回复

使用道具

 楼主| 发表于 2025-8-22 16:15 | 显示全部楼层
喜欢特效朋友在代码中换上自己制的四张图片,上面两张随便粘贴,换上自己喜欢音乐与视频。
这特效除四张图片过渡渐变,另可双叠人物在画中特点,很简单。不喜欢特效朋友单图也可。
上面两张图片行距在11.12.
四张图片行距在126.至129.
音乐行距在110.
视频行距在111.

评分

5

查看全部评分

点评
回复

使用道具

 楼主| 发表于 2025-8-22 16:16 | 显示全部楼层
本帖最后由 云端漫步 于 2025-8-22 16:46 编辑
  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>
复制代码

评分

4

查看全部评分

点评
回复

使用道具

 楼主| 发表于 2025-8-22 16:16 | 显示全部楼层
本帖最后由 云端漫步 于 2025-8-22 16:18 编辑

@一鹿向北 一鹿向北素材
更多图片 小图 大图
组图打开中,请稍候......

评分

4

查看全部评分

一鹿向北 2025-8-22 17:21
回复
你这太贴心了,都给扣好了啊。
云端漫步 2025-8-23 13:45
回复
这组人物刷你素材帖时想到可以配荷塘月色这首歌很有意境
回复

使用道具

 楼主| 发表于 2025-8-22 16:16 | 显示全部楼层
本帖最后由 云端漫步 于 2025-8-22 16:19 编辑

背景素材
http://kkshan.com/forum.php?mod=viewthread&tid=25259&extra=page%3D1

评分

1

查看全部评分

点评
回复

使用道具

 楼主| 发表于 2025-8-22 16:17 | 显示全部楼层
回复

使用道具

发表于 2025-8-22 17:24 | 显示全部楼层
这旗袍女子的素材我就是看着挺养眼,所以分享了不少。
漫步兄抠图辛苦啦,
点评
回复

使用道具

发表于 2025-8-22 18:01 | 显示全部楼层
云端漫步 发表于 2025-8-22 16:15
喜欢特效朋友在代码中换上自己制的四张图片,上面两张随便粘贴,换上自己喜欢音乐与视频。
这特效除四张图 ...

这个代码漂亮,回头可以同个代码
点评
回复

使用道具

发表于 2025-8-22 18:01 | 显示全部楼层
云端漫步 发表于 2025-8-22 16:16
@一鹿向北 一鹿向北素材

两位都太会挑了啊,这组是真的漂亮
点评
回复

使用道具

发表于 2025-8-22 18:03 | 显示全部楼层
云端漫步 发表于 2025-8-22 16:17
@令狐冲@风晴雪@云笛@轻舞若芸@仟婳@雨声@愫怡@花简静@柒玥@清梦@泪红颜@醉美水芙蓉@向荣S@落字秋风@姚云裳 ...

哈哈,来了,这组素材试着做一套,晚点发出来
点评
回复

使用道具

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

本版积分规则

手机版|千山论坛 ( 冀ICP备2024055714号 )

GMT+8, 2025-9-20 03:31

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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