马黑黑 发表于 2025-7-8 18:22

战争神曲 Novera(诺维拉)

<style>
    #papa { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: #333 url('https://638183.freep.cn/638183/t24/6/war.jpg') no-repeat center/cover; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; perspective: 2000px; z-index: 1; position: relative; --state: running; --hh: 190px; }
    .son { position: absolute; width: 30px; height: 30px; border-radius: 50%; background: url('https://638183.freep.cn/638183/small/2025/bl01.png') no-repeat center/cover; opacity: 0.5; cursor: pointer; transform: rotateZ(var(--a)) translate3d(var(--x), var(--y), var(--z)); --x: 0; --y: 0; --z: 0; --a: 0; }
    #btnFs { bottom: 20px; color: silver; border-color: silver !important; }
    #vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); opacity: .6; pointer-events: none; }
    #player { position: absolute; width: 200px; height: 200px; background: url('https://638183.freep.cn/638183/small/hxdo.png') no-repeat center/cover; transform: rotateX(45deg) rotateZ(0); cursor: pointer; animation: rot3d 6s linear infinite var(--state); filter: drop-shadow(0 0 4px gray) opacity(0.8); display: grid; place-items: center; }
    #player::after { position: absolute; content: ''; width: 30%; height: 30%; background: url('https://638183.freep.cn/638183/small/2025/bl01.png') no-repeat center/cover; }
    @keyframes rot3d { to { transform: rotateX(45deg) rotateZ(360deg); } }
</style>

<div id="papa">
    <audio id="aud" src="https://music.163.com/song/media/outer/url?id=2599491071" autoplay loop></audio>
    <video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/24/12/30/16/16/25/video677256d96857e.mp4" autoplay loop muted></video>
    <div id="player"></div>
</div>

<script type="module">
    import TWEEN from 'https://638183.freep.cn/638183/3dev/examples/jsm/libs/tween.module.js';
    import { FS } from 'https://638183.freep.cn/638183/web/ku/FS.js';

    const total = 60, sons = [], tweens = [];

    Array.from({length: total}).forEach( (son, idx) => {
      son = document.createElement('div');
      son.className = 'son';
      son.title = 'Alt+X';
      son.onclick = () => player.click();
      sons.push(son);
      papa.appendChild(son);
      const begin = {
            x: papa.clientWidth / 4 - Math.random() * papa.clientWidth / 2,
            y: 0,
            z: -5000,
            a: 0
      };
      const end = {
            x: 0,
            y: [-papa.clientHeight, papa.clientHeight / 3],
            z: [-3000, 560],
            a:
      };
      const tween = new TWEEN.Tween(begin)
            .to(end, Math.random() * 5000 + 8000)
            .onUpdate( () => {
                son.style.setProperty('--x', begin.x + 'px');
                son.style.setProperty('--y', begin.y + 'px');
                son.style.setProperty('--z', begin.z + 'px');
                son.style.setProperty('--a', begin.a + 'deg');
            })
            .delay(Math.random() * 5000)
            .repeat(Infinity)
            .repeatDelay(Math.random() * 5000)
            .easing(TWEEN.Easing.Exponential.Out)
            .yoyo(Math.random() * 30000 + 2000)
            .start();
      tweens.push(tween);
    });

    const animate = () => {
      TWEEN.update();
      requestAnimationFrame(animate);
    };

    aud.onplaying = aud.onpause = () => {
      tweens.forEach(tween => aud.paused ? tween.pause() : tween.resume());
    };

    animate();
    FS(papa, player);
</script>

马黑黑 发表于 2025-7-8 18:23

帖子代码:

<style>
    #papa { margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: #333 url('https://638183.freep.cn/638183/t24/6/war.jpg') no-repeat center/cover; box-shadow: 2px 2px 8px #000; display: grid; place-items: center; perspective: 2000px; z-index: 1; position: relative; --state: running; --hh: 190px; }
    .son { position: absolute; width: 30px; height: 30px; border-radius: 50%; background: url('https://638183.freep.cn/638183/small/2025/bl01.png') no-repeat center/cover; opacity: 0.5; cursor: pointer; transform: rotateZ(var(--a)) translate3d(var(--x), var(--y), var(--z)); --x: 0; --y: 0; --z: 0; --a: 0; }
    #btnFs { bottom: 20px; color: silver; border-color: silver !important; }
    #vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); opacity: .6; pointer-events: none; }
    #player { position: absolute; width: 200px; height: 200px; background: url('https://638183.freep.cn/638183/small/hxdo.png') no-repeat center/cover; transform: rotateX(45deg) rotateZ(0); cursor: pointer; animation: rot3d 6s linear infinite var(--state); filter: drop-shadow(0 0 4px gray) opacity(0.8); display: grid; place-items: center; }
    #player::after { position: absolute; content: ''; width: 30%; height: 30%; background: url('https://638183.freep.cn/638183/small/2025/bl01.png') no-repeat center/cover; }
    @keyframes rot3d { to { transform: rotateX(45deg) rotateZ(360deg); } }
</style>

<div id="papa">
    <audio id="aud" src="https://music.163.com/song/media/outer/url?id=2599491071" autoplay loop></audio>
    <video id="vid" src="https://bpic.588ku.com/video_listen/588ku_video/24/12/30/16/16/25/video677256d96857e.mp4" autoplay loop muted></video>
    <div id="player"></div>
</div>

<script type="module">
    import TWEEN from 'https://638183.freep.cn/638183/3dev/examples/jsm/libs/tween.module.js';
    import { FS } from 'https://638183.freep.cn/638183/web/ku/FS.js';

    const total = 60, sons = [], tweens = [];

    Array.from({length: total}).forEach( (son, idx) => {
      son = document.createElement('div');
      son.className = 'son';
      son.title = 'Alt+X';
      son.onclick = () => player.click();
      sons.push(son);
      papa.appendChild(son);
      const begin = {
            x: papa.clientWidth / 4 - Math.random() * papa.clientWidth / 2,
            y: 0,
            z: -5000,
            a: 0
      };
      const end = {
            x: 0,
            y: [-papa.clientHeight, papa.clientHeight / 3],
            z: [-3000, 560],
            a:
      };
      const tween = new TWEEN.Tween(begin)
            .to(end, Math.random() * 5000 + 8000)
            .onUpdate( () => {
                son.style.setProperty('--x', begin.x + 'px');
                son.style.setProperty('--y', begin.y + 'px');
                son.style.setProperty('--z', begin.z + 'px');
                son.style.setProperty('--a', begin.a + 'deg');
            })
            .delay(Math.random() * 5000)
            .repeat(Infinity)
            .repeatDelay(Math.random() * 5000)
            .easing(TWEEN.Easing.Exponential.Out)
            .yoyo(Math.random() * 30000 + 2000)
            .start();
      tweens.push(tween);
    });

    const animate = () => {
      TWEEN.update();
      requestAnimationFrame(animate);
    };

    aud.onplaying = aud.onpause = () => {
      tweens.forEach(tween => aud.paused ? tween.pause() : tween.resume());
    };

    animate();
    FS(papa, player);
</script>

马黑黑 发表于 2025-7-8 18:24

动画设计请参阅:


    CSS+TWEEN创意3d粒子 - 马黑黑教程专版 - 花潮论坛 - Powered by Discuz!

马黑黑 发表于 2025-7-8 18:33

本帖最后由 马黑黑 于 2025-7-8 18:34 编辑

帖子未设置 transform-style 属性,缺省默认使用 flat 转换形态,这意味着小球之间以及小球和相同场景下的其它3d元素的遮挡关系依赖于元素在代码流中的先后次序+z-index的设置。transform-style: flat; 的默认属性设置依然可以渲染3d效果,例如帖子中小球近大远小的效果存在。

当设置 transform-style: preserve-3d; 属性的容器同时又设置了防溢出的 overflow: hidden; 时,preserve-3d 将自动回退到 flat 渲染形态。

控制小球活动范围的因素是综合的,其中,在小球相关其它设置不改变的情况下,仅修改帖子容器元素的 perspective 属性值,就可以改变小球的活动区域。

红影 发表于 2025-7-8 19:01

马黑黑 发表于 2025-7-8 18:24
动画设计请参阅:




这个里面的小球运作还是和讲义里的不完全一样的呢{:4_173:}

红影 发表于 2025-7-8 19:02

“当设置 transform-style: preserve-3d; 属性的容器同时又设置了防溢出的 overflow: hidden; 时,preserve-3d 将自动回退到 flat 渲染形态。”

防溢出居然还能影响到3d,这个完全没想到。

红影 发表于 2025-7-8 19:08

音乐很激昂,有磅礴大气的史诗感,配合着这样的背景,特别有感染力{:4_199:}

杨帆 发表于 2025-7-8 19:16

奇特的效果,谢谢马老师经典讲授与示范{:4_190:}

马黑黑 发表于 2025-7-8 19:33

杨帆 发表于 2025-7-8 19:16
奇特的效果,谢谢马老师经典讲授与示范

{:4_191:}

马黑黑 发表于 2025-7-8 19:34

红影 发表于 2025-7-8 19:01
这个里面的小球运作还是和讲义里的不完全一样的呢

原理不变

马黑黑 发表于 2025-7-8 19:34

红影 发表于 2025-7-8 19:08
音乐很激昂,有磅礴大气的史诗感,配合着这样的背景,特别有感染力

嗯,打起来啦的意思

马黑黑 发表于 2025-7-8 19:37

红影 发表于 2025-7-8 19:02
“当设置 transform-style: preserve-3d; 属性的容器同时又设置了防溢出的 overflow: hidden; 时,preserve ...

我带过的一位学生,曾使用 css+HTML 做了一个三维圆球,运行完好。有一天,出于某种需要,给圆球的容器元素添加了 overflow: hidden;,结果坍塌成了差不多是平面的东东{:4_170:}

红影 发表于 2025-7-8 21:19

马黑黑 发表于 2025-7-8 19:34
原理不变

虽然原理一样,表现效果不同。这个里面播放器也被贴了同样的小图,和例子相互呼应,非常漂亮{:4_199:}

红影 发表于 2025-7-8 21:20

马黑黑 发表于 2025-7-8 19:34
嗯,打起来啦的意思

打起来应该比这更血腥,黑黑很善良,用这样的形态就表示了。

红影 发表于 2025-7-8 21:22

马黑黑 发表于 2025-7-8 19:37
我带过的一位学生,曾使用 css+HTML 做了一个三维圆球,运行完好。有一天,出于某种需要,给圆球的容器元 ...

防溢出肯定有需要的啊,比如想让视频的logo不出现,结果设置这个就会让三维坍塌啊,这个想不到呢。

马黑黑 发表于 2025-7-8 21:37

红影 发表于 2025-7-8 21:22
防溢出肯定有需要的啊,比如想让视频的logo不出现,结果设置这个就会让三维坍塌啊,这个想不到呢。

所以需要设计好逻辑关系

马黑黑 发表于 2025-7-8 21:38

红影 发表于 2025-7-8 21:20
打起来应该比这更血腥,黑黑很善良,用这样的形态就表示了。

{:4_172:}

马黑黑 发表于 2025-7-8 21:40

红影 发表于 2025-7-8 21:19
虽然原理一样,表现效果不同。这个里面播放器也被贴了同样的小图,和例子相互呼应,非常漂亮

这个简单的。开始的时候,我是让 .son 的其中一个去填充那个位置,后来想想还不如用个伪元素,旋转呀什么的都免了,更重要的是,旋转不用专门设计

红影 发表于 2025-7-8 21:59

马黑黑 发表于 2025-7-8 21:37
所以需要设计好逻辑关系

是不是它把 z 轴的延伸也当做是溢出了?

红影 发表于 2025-7-8 22:00

马黑黑 发表于 2025-7-8 21:38


这样的制作只看到了美感,没看到血腥。
页: [1] 2 3 4
查看完整版本: 战争神曲 Novera(诺维拉)